Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Charts/TemplateChart.cs @ 13401

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

#2283 added GUI and charts; fixed MCTS

File size: 5.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Windows;
6using System.Windows.Controls;
7using System.Collections;
8using System.ComponentModel;
9using System.Collections.Specialized;
10using System.Windows.Markup;
11using System.Windows.Data;
12
13namespace Microsoft.Research.DynamicDataDisplay.Charts
14{
15  /// <summary>
16  /// Represents a MVVM-friendly way to manage charts.
17  /// </summary>
18  [ContentProperty("Template")]
19  public sealed class TemplateChart : FrameworkElement, IPlotterElement
20  {
21    private readonly Dictionary<object, IPlotterElement> cache = new Dictionary<object, IPlotterElement>();
22
23    /// <summary>
24    /// Initializes a new instance of the <see cref="TemplateChart"/> class.
25    /// </summary>
26    public TemplateChart() { }
27
28    #region Properties
29
30    /// <summary>
31    /// Gets or sets the data items, used as a dataSource for generated charts. This is a DependencyProperty.
32    /// </summary>
33    /// <value>The items.</value>
34    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
35    public IEnumerable Items
36    {
37      get { return (IEnumerable)GetValue(ItemsProperty); }
38      set { SetValue(ItemsProperty, value); }
39    }
40
41    public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
42      "Items",
43      typeof(IEnumerable),
44      typeof(TemplateChart),
45      new FrameworkPropertyMetadata(null, OnItemsReplaced));
46
47    private static void OnItemsReplaced(DependencyObject d, DependencyPropertyChangedEventArgs e)
48    {
49      TemplateChart owner = (TemplateChart)d;
50
51      IEnumerable oldValue = (IEnumerable)e.OldValue;
52      IEnumerable newValue = (IEnumerable)e.NewValue;
53
54      owner.DetachOldItems(oldValue);
55      owner.AttachNewItems(newValue);
56      owner.UpdateItems();
57    }
58
59    private void UpdateItems()
60    {
61      if (plotter == null)
62        return;
63      if (Template == null)
64        return;
65      if (Items == null)
66        return;
67
68      foreach (var element in cache.Values)
69      {
70        plotter.Children.Remove(element);
71      }
72      cache.Clear();
73
74      foreach (var item in Items)
75      {
76        CreateElementAndAdd(item);
77      }
78    }
79
80    private void CreateElementAndAdd(object item)
81    {
82      FrameworkElement chart = (FrameworkElement)Template.LoadContent();
83      chart.DataContext = item;
84
85      IPlotterElement plotterElement = (IPlotterElement)chart;
86      plotter.Children.Add(plotterElement);
87      cache.Add(item, plotterElement);
88    }
89
90    private void AttachNewItems(IEnumerable items)
91    {
92      INotifyCollectionChanged observable = items as INotifyCollectionChanged;
93      if (observable != null)
94      {
95        observable.CollectionChanged += OnItems_CollectionChanged;
96      }
97    }
98
99    private void OnItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
100    {
101      if (plotter == null)
102        return;
103      if (Template == null)
104        return;
105
106      if (e.Action == NotifyCollectionChangedAction.Reset)
107      {
108        UpdateItems();
109        return;
110      }
111
112      if (e.OldItems != null)
113      {
114        foreach (var removedData in e.OldItems)
115        {
116          var plotterElement = cache[removedData];
117
118          plotter.Children.Remove(plotterElement);
119
120          cache.Remove(removedData);
121        }
122      }
123
124      if (e.NewItems != null)
125      {
126        foreach (var addedData in e.NewItems)
127        {
128          CreateElementAndAdd(addedData);
129        }
130      }
131    }
132
133    private void DetachOldItems(IEnumerable items)
134    {
135      INotifyCollectionChanged observable = items as INotifyCollectionChanged;
136      if (observable != null)
137      {
138        observable.CollectionChanged -= OnItems_CollectionChanged;
139      }
140    }
141
142    /// <summary>
143    /// Gets or sets the template, used to generate charts for each data item. This is a DependencyProperty.
144    /// </summary>
145    /// <value>The template.</value>
146    public ControlTemplate Template
147    {
148      get { return (ControlTemplate)GetValue(TemplateProperty); }
149      set { SetValue(TemplateProperty, value); }
150    }
151
152    public static readonly DependencyProperty TemplateProperty = DependencyProperty.Register(
153      "Template",
154      typeof(ControlTemplate),
155      typeof(TemplateChart),
156      new FrameworkPropertyMetadata(null, OnTemplateReplaced));
157
158    private static void OnTemplateReplaced(DependencyObject d, DependencyPropertyChangedEventArgs e)
159    {
160      TemplateChart owner = (TemplateChart)d;
161      owner.UpdateItems();
162    }
163
164    #endregion
165
166    private Plotter2D plotter;
167
168    #region IPlotterElement Members
169
170    /// <summary>
171    /// Called when parent plotter is attached.
172    /// Allows to, for example, add custom UI parts to ChartPlotter's visual tree or subscribe to ChartPlotter's events.
173    /// </summary>
174    /// <param name="plotter">The parent plotter.</param>
175    public void OnPlotterAttached(Plotter plotter)
176    {
177      this.plotter = (Plotter2D)plotter;
178      SetBinding(DataContextProperty, new Binding("DataContext") { Source = plotter });
179      UpdateItems();
180    }
181
182    /// <summary>
183    /// Called when item is being detached from parent plotter.
184    /// Allows to remove added in OnPlotterAttached method UI parts or unsubscribe from events.
185    /// This should be done as each chart can be added only one Plotter at one moment of time.
186    /// </summary>
187    /// <param name="plotter">The plotter.</param>
188    public void OnPlotterDetaching(Plotter plotter)
189    {
190      foreach (var element in cache.Values)
191      {
192        plotter.Children.Remove(element);
193      }
194      BindingOperations.ClearBinding(this, DataContextProperty);
195      this.plotter = null;
196    }
197
198    /// <summary>
199    /// Gets the parent plotter of chart.
200    /// Should be equal to null if item is not connected to any plotter.
201    /// </summary>
202    /// <value>The plotter.</value>
203    public Plotter2D Plotter
204    {
205      get { return plotter; }
206    }
207
208    /// <summary>
209    /// Gets the parent plotter of chart.
210    /// Should be equal to null if item is not connected to any plotter.
211    /// </summary>
212    /// <value>The plotter.</value>
213    Plotter IPlotterElement.Plotter
214    {
215      get { return plotter; }
216    }
217
218    #endregion
219  }
220}
Note: See TracBrowser for help on using the repository browser.