tankiconmaker /Layer.cs

Language C# Lines 133
MD5 Hash 1e7b15b56f6f944578fef49ea284a6f9 Estimated Cost $2,433 (why?)
Repository https://bitbucket.org/rstarkov/tankiconmaker View Raw File View Project SPDX
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Linq;
using RT.Util.Lingo;
using RT.Util.Serialization;
using WpfCrutches;

namespace TankIconMaker
{
    abstract class LayerBase : IHasTreeViewItem, IHasTypeNameDescription, IClassifyXmlObjectProcessor, INotifyPropertyChanged
    {
        /// <summary>Describes what this layer type does as concisely as possible.</summary>
        [Browsable(false)]
        public abstract string TypeName { get; }
        /// <summary>Describes what this layer type does in more detail.</summary>
        [Browsable(false)]
        public abstract string TypeDescription { get; }
        /// <summary>Specifies the version of this layer’s settings - incremented on changing layer settings backwards-incompatibly.</summary>
        [Browsable(false)]
        public abstract int Version { get; }

        [Browsable(false)]
        public string Name { get { return _Name; } set { _Name = value; NotifyPropertyChanged("Name"); NotifyPropertyChanged("NameVisibility"); } }
        private string _Name;

        [Browsable(false)]
        public Visibility NameVisibility { get { return string.IsNullOrEmpty(Name) ? Visibility.Collapsed : Visibility.Visible; } }

        /// <summary>Keeps track of the style that this layer belongs to. This value is kept up-to-date automatically.</summary>
        [Browsable(false), ClassifyIgnore]
        public Style ParentStyle { get; set; }
        [Browsable(false)]
        public ObservableCollection<EffectBase> Effects { get; set; }

        /// <summary>Id for use in Layer Mask.</summary>
        private string _Id;
        public string Id { get { return _Id; } set { _Id = Regex.Replace(Regex.Replace(value, @"[^A-Za-z0-9_]", ""), @"^([0-9])", "_$1"); NotifyPropertyChanged("Id"); } }
        public static MemberTr IdTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerId); }

        public bool Visible { get { return _Visible; } set { _Visible = value; NotifyPropertyChanged("Visible"); } }
        private bool _Visible;
        public static MemberTr VisibleTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerVisible); }

        public ValueSelector<BoolWithPassthrough> VisibleFor { get; set; }
        public static MemberTr VisibleForTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerVisibleFor); }

        public LayerBase()
        {
            Effects = new ObservableCollection<EffectBase>();
            Effects.CollectionChanged += updateEffectLayer;
            Visible = true;
            VisibleFor = new ValueSelector<BoolWithPassthrough>(BoolWithPassthrough.Yes);
        }

        private void updateEffectLayer(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
                foreach (var item in e.NewItems.OfType<EffectBase>())
                    item.Layer = this;
            else if (e.Action == NotifyCollectionChangedAction.Reset)
                foreach (var item in Effects)
                    item.Layer = this;
        }

        /// <summary>
        /// Returns this layer's image for this tank. Will be called from multiple threads in parallel. The result may be any size. Return
        /// a writable image if it may be modified directly, or mark it as read-only otherwise.
        /// </summary>
        public abstract BitmapBase Draw(Tank tank);

        /// <summary>
        /// Stores the <see cref="Version"/> of the maker as it was at the time of saving settings to XML. This may
        /// then be used to apply transformations to the XML produced by old versions of a layer.
        /// </summary>
        protected int SavedByVersion;

        void IClassifyObjectProcessor<XElement>.BeforeSerialize() { BeforeSerialize(); }
        protected virtual void BeforeSerialize()
        {
            SavedByVersion = Version;
        }

        void IClassifyObjectProcessor<XElement>.AfterSerialize(XElement xml) { AfterSerialize(xml); }
        protected virtual void AfterSerialize(XElement xml) { }

        void IClassifyObjectProcessor<XElement>.BeforeDeserialize(XElement xml) { BeforeDeserialize(xml); }
        protected virtual void BeforeDeserialize(XElement xml) { }

        void IClassifyObjectProcessor<XElement>.AfterDeserialize(XElement xml) { AfterDeserialize(xml); }
        protected virtual void AfterDeserialize(XElement xml)
        {
            foreach (var effect in Effects)
                effect.Layer = this;
            var oldSizePosEffects = Effects.Where(e => e is Effects.SizePosEffect && e.SavedByVersion <= 2).ToList();
            if (oldSizePosEffects.Any())
            {
                oldSizePosEffects.Reverse();
                foreach (var e in oldSizePosEffects)
                {
                    Effects.Remove(e);
                    Effects.Insert(0, e);
                }
            }
            Effects.CollectionChanged -= updateEffectLayer;
            Effects.CollectionChanged += updateEffectLayer;
        }

        [ClassifyIgnore, Browsable(false)]
        public TreeViewItem TreeViewItem { get; set; }

        protected void NotifyPropertyChanged(string name) { PropertyChanged(this, new PropertyChangedEventArgs(name)); }
        public event PropertyChangedEventHandler PropertyChanged = (_, __) => { };

        public virtual LayerBase Clone()
        {
            var result = MemberwiseClone() as LayerBase;
            result.PropertyChanged = (_, __) => { };
            result.TreeViewItem = null;
            result.VisibleFor = VisibleFor.Clone();
            result.Effects = new ObservableCollection<EffectBase>();
            result.Effects.CollectionChanged += result.updateEffectLayer;
            foreach (var e in Effects)
                result.Effects.Add(e.Clone());
            return result;
        }
    }
}
Back to Top