Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/DataSources/OneDimensional/ObservableDataSource.cs @ 12503

Last change on this file since 12503 was 12503, checked in by aballeit, 9 years ago

#2283 added GUI and charts; fixed MCTS

File size: 4.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Collections.ObjectModel;
4using System.Collections.Specialized;
5using System.Windows;
6using System.Windows.Threading;
7
8namespace Microsoft.Research.DynamicDataDisplay.DataSources
9{
10  // todo I don't think that we should create data source which supports
11  // suspending its DataChanged event - it is better to create
12  // collection with the same functionality - then it would be able to be used
13  // as a source in many data sources.
14  public class ObservableDataSource<T> : IPointDataSource
15  {
16
17    /// <summary>True if collection was changed between SuspendUpdate and ResumeUpdate
18    /// or false otherwise</summary>
19    private bool collectionChanged = false;
20
21    /// <summary>True if event should be raised on each collection change
22    /// or false otherwise</summary>
23    private bool updatesEnabled = true;
24
25    public ObservableDataSource()
26    {
27      collection.CollectionChanged += OnCollectionChanged;
28
29      // todo this is hack
30      if (typeof(T) == typeof(Point))
31      {
32        xyMapping = t => (Point)(object)t;
33      }
34    }
35
36    public ObservableDataSource(IEnumerable<T> data)
37      : this()
38    {
39      if (data == null)
40        throw new ArgumentNullException("data");
41
42      foreach (T item in data)
43      {
44        collection.Add(item);
45      }
46    }
47
48    public void SuspendUpdate()
49    {
50      updatesEnabled = false;
51    }
52
53    public void ResumeUpdate()
54    {
55      updatesEnabled = true;
56      if (collectionChanged)
57      {
58        collectionChanged = false;
59        RaiseDataChanged();
60      }
61    }
62
63    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
64    {
65      if (updatesEnabled)
66      {
67        RaiseDataChanged();
68      }
69      else
70      {
71        collectionChanged = true;
72      }
73    }
74
75    private readonly ObservableCollection<T> collection = new ObservableCollection<T>();
76
77    public ObservableCollection<T> Collection
78    {
79      get { return collection; }
80    }
81
82    public void AppendMany(IEnumerable<T> data)
83    {
84      if (data == null)
85        throw new ArgumentNullException("data");
86
87      updatesEnabled = false;
88      foreach (var p in data)
89      {
90        collection.Add(p);
91      }
92      updatesEnabled = true;
93      RaiseDataChanged();
94    }
95
96    public void AppendAsync(Dispatcher dispatcher, T item)
97    {
98      dispatcher.Invoke(DispatcherPriority.Normal,
99        new Action(() =>
100        {
101          collection.Add(item);
102          RaiseDataChanged();
103        }));
104    }
105
106    private readonly List<Mapping<T>> mappings = new List<Mapping<T>>();
107    private Func<T, double> xMapping;
108    private Func<T, double> yMapping;
109    private Func<T, Point> xyMapping;
110
111    public void SetXMapping(Func<T, double> mapping)
112    {
113      if (mapping == null)
114        throw new ArgumentNullException("mapping");
115
116      this.xMapping = mapping;
117    }
118
119    public void SetYMapping(Func<T, double> mapping)
120    {
121      if (mapping == null)
122        throw new ArgumentNullException("mapping");
123
124      this.yMapping = mapping;
125    }
126
127    public void SetXYMapping(Func<T, Point> mapping)
128    {
129      if (mapping == null)
130        throw new ArgumentNullException("mapping");
131
132      this.xyMapping = mapping;
133    }
134
135    #region IChartDataSource Members
136
137    private class ObservableIterator : IPointEnumerator
138    {
139      private readonly ObservableDataSource<T> dataSource;
140      private readonly IEnumerator<T> enumerator;
141
142      public ObservableIterator(ObservableDataSource<T> dataSource)
143      {
144        this.dataSource = dataSource;
145        enumerator = dataSource.collection.GetEnumerator();
146      }
147
148      #region IChartPointEnumerator Members
149
150      public bool MoveNext()
151      {
152        return enumerator.MoveNext();
153      }
154
155      public void GetCurrent(ref Point p)
156      {
157        dataSource.FillPoint(enumerator.Current, ref p);
158      }
159
160      public void ApplyMappings(DependencyObject target)
161      {
162        dataSource.ApplyMappings(target, enumerator.Current);
163      }
164
165      public void Dispose()
166      {
167        enumerator.Dispose();
168        GC.SuppressFinalize(this);
169      }
170
171      #endregion
172    }
173
174    private void FillPoint(T elem, ref Point point)
175    {
176      if (xyMapping != null)
177      {
178        point = xyMapping(elem);
179      }
180      else
181      {
182        if (xMapping != null)
183        {
184          point.X = xMapping(elem);
185        }
186        if (yMapping != null)
187        {
188          point.Y = yMapping(elem);
189        }
190      }
191    }
192
193    private void ApplyMappings(DependencyObject target, T elem)
194    {
195      if (target != null)
196      {
197        foreach (var mapping in mappings)
198        {
199          target.SetValue(mapping.Property, mapping.F(elem));
200        }
201      }
202    }
203
204    public IPointEnumerator GetEnumerator(DependencyObject context)
205    {
206      return new ObservableIterator(this);
207    }
208
209    public event EventHandler DataChanged;
210    private void RaiseDataChanged()
211    {
212      if (DataChanged != null)
213      {
214        DataChanged(this, EventArgs.Empty);
215      }
216    }
217
218    #endregion
219  }
220}
Note: See TracBrowser for help on using the repository browser.