Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/ViewportElement2D.cs @ 13834

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

#2283 added GUI and charts; fixed MCTS

File size: 10.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Diagnostics;
5using System.Globalization;
6using System.Threading;
7using System.Windows;
8using System.Windows.Controls;
9using System.Windows.Media;
10using System.Windows.Media.Imaging;
11using System.Windows.Threading;
12using Microsoft.Research.DynamicDataDisplay.Common;
13
14namespace Microsoft.Research.DynamicDataDisplay
15{
16  /// <summary>ViewportElement2D is intended to be a child of Viewport2D. Specifics
17  /// of ViewportElement2D is Viewport2D attached property</summary>
18  public abstract class ViewportElement2D : PlotterElement, INotifyPropertyChanged
19  {
20    protected ViewportElement2D() { }
21
22    protected virtual Panel GetHostPanel(Plotter plotter)
23    {
24      return plotter.CentralGrid;
25    }
26
27    protected override void OnPlotterAttached(Plotter plotter)
28    {
29      base.OnPlotterAttached(plotter);
30
31      plotter2D = (Plotter2D)plotter;
32      GetHostPanel(plotter).Children.Add(this);
33      viewport = plotter2D.Viewport;
34      viewport.PropertyChanged += OnViewportPropertyChanged;
35    }
36
37    private void OnViewportPropertyChanged(object sender, ExtendedPropertyChangedEventArgs e)
38    {
39      if (e.PropertyName == "Visible")
40      {
41        OnVisibleChanged((DataRect)e.NewValue, (DataRect)e.OldValue);
42      }
43      else if (e.PropertyName == "Output")
44      {
45        OnOutputChanged((Rect)e.NewValue, (Rect)e.OldValue);
46      }
47      else if (e.PropertyName == "Transform")
48      {
49        Update();
50      }
51      else
52      {
53        // other properties changed are now not interesting for us
54      }
55    }
56
57    protected override void OnPlotterDetaching(Plotter plotter)
58    {
59      base.OnPlotterDetaching(plotter);
60
61      viewport.PropertyChanged -= OnViewportPropertyChanged;
62      viewport = null;
63      GetHostPanel(plotter).Children.Remove(this);
64      plotter2D = null;
65    }
66
67    private Plotter2D plotter2D;
68    protected Plotter2D Plotter2D
69    {
70      get { return plotter2D; }
71    }
72
73    public int ZIndex
74    {
75      get { return Panel.GetZIndex(this); }
76      set { Panel.SetZIndex(this, value); }
77    }
78
79    #region Viewport
80
81    private Viewport2D viewport;
82    protected Viewport2D Viewport
83    {
84      get { return viewport; }
85    }
86
87    #endregion
88
89    private Vector offset = new Vector();
90    protected internal Vector Offset
91    {
92      get { return offset; }
93      set { offset = value; }
94    }
95
96    //bool SizeEqual(Size s1, Size s2, double eps)
97    //{
98    //    double width = Math.Min(s1.Width, s2.Width);
99    //    double height = Math.Min(s1.Height, s2.Height);
100    //    return Math.Abs(s1.Width - s2.Width) < width * eps &&
101    //           Math.Abs(s1.Height - s2.Height) < height * eps;
102    //}
103
104    protected virtual void OnVisibleChanged(DataRect newRect, DataRect oldRect)
105    {
106      if (newRect.Size == oldRect.Size)
107      {
108        var transform = viewport.Transform;
109        offset += oldRect.Location.DataToScreen(transform) - newRect.Location.DataToScreen(transform);
110        if (ManualTranslate)
111        {
112          Update();
113        }
114      }
115      else
116      {
117        offset = new Vector();
118        Update();
119      }
120    }
121
122    protected virtual void OnOutputChanged(Rect newRect, Rect oldRect)
123    {
124      offset = new Vector();
125      Update();
126    }
127
128    /// <summary>
129    /// Gets a value indicating whether this instance is translated.
130    /// </summary>
131    /// <value>
132    ///   <c>true</c> if this instance is translated; otherwise, <c>false</c>.
133    /// </value>
134    protected bool IsTranslated
135    {
136      get { return offset.X != 0 || offset.Y != 0; }
137    }
138
139    #region IsLevel
140
141    public bool IsLayer
142    {
143      get { return (bool)GetValue(IsLayerProperty); }
144      set { SetValue(IsLayerProperty, value); }
145    }
146
147    public static readonly DependencyProperty IsLayerProperty =
148      DependencyProperty.Register(
149      "IsLayer",
150      typeof(bool),
151      typeof(ViewportElement2D),
152      new FrameworkPropertyMetadata(
153        false
154        ));
155
156    #endregion
157
158    #region Rendering & caching options
159
160    protected object GetValueSync(DependencyProperty property)
161    {
162      return Dispatcher.Invoke(
163              DispatcherPriority.Send,
164               (DispatcherOperationCallback)delegate { return GetValue(property); },
165              property);
166    }
167
168    protected void SetValueAsync(DependencyProperty property, object value)
169    {
170      Dispatcher.BeginInvoke(DispatcherPriority.Send,
171        (SendOrPostCallback)delegate { SetValue(property, value); },
172        value);
173    }
174
175    private bool manualClip;
176    /// <summary>
177    /// Gets or sets a value indicating whether descendant graph class
178    /// relies on autotic clipping by Viewport.Output or
179    /// does its own clipping.
180    /// </summary>
181    public bool ManualClip
182    {
183      get { return manualClip; }
184      set { manualClip = value; }
185    }
186
187    private bool manualTranslate;
188    /// <summary>
189    /// Gets or sets a value indicating whether descendant graph class
190    /// relies on automatic translation of it, or does its own.
191    /// </summary>
192    public bool ManualTranslate
193    {
194      get { return manualTranslate; }
195      set { manualTranslate = value; }
196    }
197
198    private RenderTo renderTarget = RenderTo.Screen;
199    /// <summary>
200    /// Gets or sets a value indicating whether descendant graph class
201    /// uses cached rendering of its content to image, or not.
202    /// </summary>
203    public RenderTo RenderTarget
204    {
205      get { return renderTarget; }
206      set { renderTarget = value; }
207    }
208
209    private enum ImageKind
210    {
211      Real,
212      BeingRendered,
213      Empty
214    }
215
216    #endregion
217
218    private RenderState CreateRenderState(DataRect renderVisible, RenderTo renderingType)
219    {
220      Rect output = Viewport.Output;
221
222      return new RenderState(renderVisible, Viewport.Visible,
223        output,
224        renderingType);
225    }
226
227    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
228    {
229      base.OnPropertyChanged(e);
230
231      if (e.Property == VisibilityProperty)
232      {
233        Update();
234      }
235    }
236
237    private bool updateCalled;
238    private bool beforeFirstUpdate = true;
239    protected void Update()
240    {
241      if (Viewport == null) return;
242
243      UpdateCore();
244
245      if (!beforeFirstUpdate)
246      {
247        updateCalled = true;
248        InvalidateVisual();
249      }
250      beforeFirstUpdate = false;
251    }
252
253    protected virtual void UpdateCore() { }
254
255    protected void TranslateVisual()
256    {
257      if (!ManualTranslate)
258      {
259        shouldReRender = false;
260      }
261      InvalidateVisual();
262    }
263
264    #region Thumbnail
265
266    private ImageSource thumbnail;
267    public ImageSource Thumbnail
268    {
269      get
270      {
271        if (!CreateThumbnail)
272        {
273          CreateThumbnail = true;
274        }
275        return thumbnail;
276      }
277    }
278
279    private bool createThumbnail;
280    public bool CreateThumbnail
281    {
282      get { return createThumbnail; }
283      set
284      {
285        if (createThumbnail != value)
286        {
287          createThumbnail = value;
288          if (value)
289          {
290            RenderThumbnail();
291          }
292          else
293          {
294            thumbnail = null;
295            RaisePropertyChanged("Thumbnail");
296          }
297        }
298      }
299    }
300
301    private bool ShouldCreateThumbnail
302    {
303      get { return IsLayer && createThumbnail; }
304    }
305
306    private void RenderThumbnail()
307    {
308      if (Viewport == null) return;
309
310      Rect output = Viewport.Output;
311      if (output.Width == 0 || output.Height == 0)
312        return;
313
314      DataRect visible = Viewport.Visible;
315
316      var transform = viewport.Transform;
317
318      DrawingVisual visual = new DrawingVisual();
319      using (DrawingContext dc = visual.RenderOpen())
320      {
321        Point outputStart = visible.Location.DataToScreen(transform);
322        double x = -outputStart.X + offset.X;
323        double y = -outputStart.Y + output.Bottom - output.Top + offset.Y;
324        bool translate = !manualTranslate && IsTranslated;
325        if (translate)
326        {
327          dc.PushTransform(new TranslateTransform(x, y));
328        }
329
330        const byte c = 240;
331        Brush brush = new SolidColorBrush(Color.FromArgb(120, c, c, c));
332        Pen pen = new Pen(Brushes.Black, 1);
333        dc.DrawRectangle(brush, pen, output);
334        dc.DrawDrawing(graphContents);
335
336        if (translate)
337        {
338          dc.Pop();
339        }
340      }
341
342      RenderTargetBitmap bmp = new RenderTargetBitmap((int)output.Width, (int)output.Height, 96, 96, PixelFormats.Pbgra32);
343      bmp.Render(visual);
344      thumbnail = bmp;
345      RaisePropertyChanged("Thumbnail");
346    }
347
348    #endregion
349
350    private bool shouldReRender = true;
351    private DrawingGroup graphContents;
352    protected sealed override void OnRender(DrawingContext drawingContext)
353    {
354      if (Viewport == null) return;
355
356      Rect output = Viewport.Output;
357      if (output.Width == 0 || output.Height == 0) return;
358      if (output.IsEmpty) return;
359      if (Visibility != Visibility.Visible) return;
360
361      if (shouldReRender || manualTranslate || renderTarget == RenderTo.Image || beforeFirstUpdate || updateCalled)
362      {
363        if (graphContents == null)
364        {
365          graphContents = new DrawingGroup();
366        }
367        if (beforeFirstUpdate)
368        {
369          Update();
370        }
371
372        using (DrawingContext context = graphContents.Open())
373        {
374          if (renderTarget == RenderTo.Screen)
375          {
376            RenderState state = CreateRenderState(Viewport.Visible, RenderTo.Screen);
377            OnRenderCore(context, state);
378          }
379          else
380          {
381            // for future use
382          }
383        }
384        updateCalled = false;
385      }
386
387      // thumbnail is not created, if
388      // 1) CreateThumbnail is false
389      // 2) this graph has IsLayer property, set to false
390      if (ShouldCreateThumbnail)
391      {
392        RenderThumbnail();
393      }
394
395      if (!manualClip)
396      {
397        drawingContext.PushClip(new RectangleGeometry(output));
398      }
399      bool translate = !manualTranslate && IsTranslated;
400      if (translate)
401      {
402        drawingContext.PushTransform(new TranslateTransform(offset.X, offset.Y));
403      }
404
405      drawingContext.DrawDrawing(graphContents);
406
407      if (translate)
408      {
409        drawingContext.Pop();
410      }
411      if (!manualClip)
412      {
413        drawingContext.Pop();
414      }
415      shouldReRender = true;
416    }
417
418
419    protected abstract void OnRenderCore(DrawingContext dc, RenderState state);
420
421    #region INotifyPropertyChanged Members
422
423    public event PropertyChangedEventHandler PropertyChanged;
424
425    protected void RaisePropertyChanged(string propertyName)
426    {
427      if (PropertyChanged != null)
428      {
429        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
430      }
431    }
432
433    #endregion
434  }
435}
Note: See TracBrowser for help on using the repository browser.