PageRenderTime 28ms CodeModel.GetById 16ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/Layer.cs

https://bitbucket.org/rstarkov/tankiconmaker
C# | 132 lines | 101 code | 18 blank | 13 comment | 9 complexity | 1e7b15b56f6f944578fef49ea284a6f9 MD5 | raw file
  1using System.Collections.ObjectModel;
  2using System.Collections.Specialized;
  3using System.ComponentModel;
  4using System.Linq;
  5using System.Text.RegularExpressions;
  6using System.Windows;
  7using System.Windows.Controls;
  8using System.Xml.Linq;
  9using RT.Util.Lingo;
 10using RT.Util.Serialization;
 11using WpfCrutches;
 12
 13namespace TankIconMaker
 14{
 15    abstract class LayerBase : IHasTreeViewItem, IHasTypeNameDescription, IClassifyXmlObjectProcessor, INotifyPropertyChanged
 16    {
 17        /// <summary>Describes what this layer type does as concisely as possible.</summary>
 18        [Browsable(false)]
 19        public abstract string TypeName { get; }
 20        /// <summary>Describes what this layer type does in more detail.</summary>
 21        [Browsable(false)]
 22        public abstract string TypeDescription { get; }
 23        /// <summary>Specifies the version of this layer’s settings - incremented on changing layer settings backwards-incompatibly.</summary>
 24        [Browsable(false)]
 25        public abstract int Version { get; }
 26
 27        [Browsable(false)]
 28        public string Name { get { return _Name; } set { _Name = value; NotifyPropertyChanged("Name"); NotifyPropertyChanged("NameVisibility"); } }
 29        private string _Name;
 30
 31        [Browsable(false)]
 32        public Visibility NameVisibility { get { return string.IsNullOrEmpty(Name) ? Visibility.Collapsed : Visibility.Visible; } }
 33
 34        /// <summary>Keeps track of the style that this layer belongs to. This value is kept up-to-date automatically.</summary>
 35        [Browsable(false), ClassifyIgnore]
 36        public Style ParentStyle { get; set; }
 37        [Browsable(false)]
 38        public ObservableCollection<EffectBase> Effects { get; set; }
 39
 40        /// <summary>Id for use in Layer Mask.</summary>
 41        private string _Id;
 42        public string Id { get { return _Id; } set { _Id = Regex.Replace(Regex.Replace(value, @"[^A-Za-z0-9_]", ""), @"^([0-9])", "_$1"); NotifyPropertyChanged("Id"); } }
 43        public static MemberTr IdTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerId); }
 44
 45        public bool Visible { get { return _Visible; } set { _Visible = value; NotifyPropertyChanged("Visible"); } }
 46        private bool _Visible;
 47        public static MemberTr VisibleTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerVisible); }
 48
 49        public ValueSelector<BoolWithPassthrough> VisibleFor { get; set; }
 50        public static MemberTr VisibleForTr(Translation tr) { return new MemberTr(tr.Category.General, tr.LayerAndEffect.LayerVisibleFor); }
 51
 52        public LayerBase()
 53        {
 54            Effects = new ObservableCollection<EffectBase>();
 55            Effects.CollectionChanged += updateEffectLayer;
 56            Visible = true;
 57            VisibleFor = new ValueSelector<BoolWithPassthrough>(BoolWithPassthrough.Yes);
 58        }
 59
 60        private void updateEffectLayer(object sender, NotifyCollectionChangedEventArgs e)
 61        {
 62            if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
 63                foreach (var item in e.NewItems.OfType<EffectBase>())
 64                    item.Layer = this;
 65            else if (e.Action == NotifyCollectionChangedAction.Reset)
 66                foreach (var item in Effects)
 67                    item.Layer = this;
 68        }
 69
 70        /// <summary>
 71        /// Returns this layer's image for this tank. Will be called from multiple threads in parallel. The result may be any size. Return
 72        /// a writable image if it may be modified directly, or mark it as read-only otherwise.
 73        /// </summary>
 74        public abstract BitmapBase Draw(Tank tank);
 75
 76        /// <summary>
 77        /// Stores the <see cref="Version"/> of the maker as it was at the time of saving settings to XML. This may
 78        /// then be used to apply transformations to the XML produced by old versions of a layer.
 79        /// </summary>
 80        protected int SavedByVersion;
 81
 82        void IClassifyObjectProcessor<XElement>.BeforeSerialize() { BeforeSerialize(); }
 83        protected virtual void BeforeSerialize()
 84        {
 85            SavedByVersion = Version;
 86        }
 87
 88        void IClassifyObjectProcessor<XElement>.AfterSerialize(XElement xml) { AfterSerialize(xml); }
 89        protected virtual void AfterSerialize(XElement xml) { }
 90
 91        void IClassifyObjectProcessor<XElement>.BeforeDeserialize(XElement xml) { BeforeDeserialize(xml); }
 92        protected virtual void BeforeDeserialize(XElement xml) { }
 93
 94        void IClassifyObjectProcessor<XElement>.AfterDeserialize(XElement xml) { AfterDeserialize(xml); }
 95        protected virtual void AfterDeserialize(XElement xml)
 96        {
 97            foreach (var effect in Effects)
 98                effect.Layer = this;
 99            var oldSizePosEffects = Effects.Where(e => e is Effects.SizePosEffect && e.SavedByVersion <= 2).ToList();
100            if (oldSizePosEffects.Any())
101            {
102                oldSizePosEffects.Reverse();
103                foreach (var e in oldSizePosEffects)
104                {
105                    Effects.Remove(e);
106                    Effects.Insert(0, e);
107                }
108            }
109            Effects.CollectionChanged -= updateEffectLayer;
110            Effects.CollectionChanged += updateEffectLayer;
111        }
112
113        [ClassifyIgnore, Browsable(false)]
114        public TreeViewItem TreeViewItem { get; set; }
115
116        protected void NotifyPropertyChanged(string name) { PropertyChanged(this, new PropertyChangedEventArgs(name)); }
117        public event PropertyChangedEventHandler PropertyChanged = (_, __) => { };
118
119        public virtual LayerBase Clone()
120        {
121            var result = MemberwiseClone() as LayerBase;
122            result.PropertyChanged = (_, __) => { };
123            result.TreeViewItem = null;
124            result.VisibleFor = VisibleFor.Clone();
125            result.Effects = new ObservableCollection<EffectBase>();
126            result.Effects.CollectionChanged += result.updateEffectLayer;
127            foreach (var e in Effects)
128                result.Effects.Add(e.Clone());
129            return result;
130        }
131    }
132}