Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization/DynamicDataDisplay/Charts/BitmapBasedGraph.cs @ 13072

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

#2283 added GUI and charts; fixed MCTS

File size: 8.6 KB
Line 
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Threading;
6//using System.Threading.Tasks;
7using System.Windows;
8using System.Windows.Controls;
9using System.Windows.Controls.Primitives;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Shapes;
13using Microsoft.Research.DynamicDataDisplay.Charts;
14using Microsoft.Research.DynamicDataDisplay.Common;
15using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
16using Microsoft.Research.DynamicDataDisplay.DataSources;
17using Microsoft.Research.DynamicDataDisplay.PointMarkers;
18using Microsoft.Research.DynamicDataDisplay.Charts.Shapes;
19using System.Windows.Input;
20
21namespace Microsoft.Research.DynamicDataDisplay
22{
23  public abstract class BitmapBasedGraph : ViewportElement2D, IDisposable
24  {
25    static BitmapBasedGraph()
26    {
27      Type thisType = typeof(BitmapBasedGraph);
28      BackgroundRenderer.UsesBackgroundRenderingProperty.OverrideMetadata(thisType, new FrameworkPropertyMetadata(true));
29        }
30
31        private int disposed = 0;
32
33    private int nextRequestId = 0;
34
35    /// <summary>Latest complete request</summary>
36    private RenderRequest completedRequest = null;
37
38    /// <summary>Currently running request</summary>
39    private RenderRequest activeRequest = null;
40
41    /// <summary>Result of latest complete request</summary>
42    private BitmapSource completedBitmap = null;
43
44    /// <summary>Pending render request</summary>
45    private RenderRequest pendingRequest = null;
46
47    /// <summary>Single apartment thread used for background rendering</summary>
48    /// <remarks>STA is required for creating WPF components in this thread</remarks>
49    private Thread renderThread = null;
50
51    private AutoResetEvent renderRequested = new AutoResetEvent(false);
52
53    private ManualResetEvent shutdownRequested = new ManualResetEvent(false);
54
55    /// <summary>True means that current bitmap is invalidated and is to be re-rendered.</summary>
56    private bool bitmapInvalidated = true;
57
58    /// <summary>Shows tooltips.</summary>
59    private PopupTip popup;
60
61    /// <summary>
62    /// Initializes a new instance of the <see cref="MarkerPointsGraph"/> class.
63    /// </summary>
64    public BitmapBasedGraph()
65    {
66      ManualTranslate = true;
67    }
68
69    protected virtual UIElement GetTooltipForPoint(Point point, DataRect visible, Rect output)
70    {
71      return null;
72    }
73
74    protected PopupTip GetPopupTipWindow()
75    {
76      if (popup != null)
77        return popup;
78
79      foreach (var item in Plotter.Children)
80      {
81        if (item is ViewportUIContainer)
82        {
83          ViewportUIContainer container = (ViewportUIContainer)item;
84          if (container.Content is PopupTip)
85            return popup = (PopupTip)container.Content;
86        }
87      }
88
89      popup = new PopupTip();
90      popup.Placement = PlacementMode.Relative;
91      popup.PlacementTarget = this;
92      Plotter.Children.Add(popup);
93      return popup;
94    }
95
96    protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
97    {
98      base.OnMouseMove(e);
99
100      var popup = GetPopupTipWindow();
101      if (popup.IsOpen)
102        popup.Hide();
103
104      if (bitmapInvalidated) return;
105
106      Point p = e.GetPosition(this);
107      Point dp = p.ScreenToData(Plotter2D.Transform);
108
109      var tooltip = GetTooltipForPoint(p, completedRequest.Visible, completedRequest.Output);
110      if (tooltip == null) return;
111
112      popup.VerticalOffset = p.Y + 20;
113      popup.HorizontalOffset = p.X;
114
115      popup.ShowDelayed(new TimeSpan(0, 0, 1));
116
117      Grid grid = new Grid();
118
119      Rectangle rect = new Rectangle
120      {
121        Stroke = Brushes.Black,
122        Fill = SystemColors.InfoBrush
123      };
124
125      StackPanel sp = new StackPanel();
126      sp.Orientation = Orientation.Vertical;
127      sp.Children.Add(tooltip);
128      sp.Margin = new Thickness(4, 2, 4, 2);
129
130      var tb = new TextBlock();
131      tb.Text = String.Format("Location: {0:F2}, {1:F2}", dp.X, dp.Y);
132      tb.Foreground = SystemColors.GrayTextBrush;
133      sp.Children.Add(tb);
134
135      grid.Children.Add(rect);
136      grid.Children.Add(sp);
137      grid.Measure(SizeHelper.CreateInfiniteSize());
138      popup.Child = grid;
139    }
140
141    protected override void OnMouseLeave(MouseEventArgs e)
142    {
143      base.OnMouseLeave(e);
144      GetPopupTipWindow().Hide();
145    }
146
147    /// <summary>
148    /// Adds a render task and invalidates visual.
149    /// </summary>
150    public void UpdateVisualization()
151    {
152      if (Viewport == null) return;
153
154      Rect output = new Rect(this.RenderSize);
155      CreateRenderTask(Viewport.Visible, output);
156      InvalidateVisual();
157    }
158
159    protected override void OnVisibleChanged(DataRect newRect, DataRect oldRect)
160    {
161      base.OnVisibleChanged(newRect, oldRect);
162      CreateRenderTask(newRect, Viewport.Output);
163      InvalidateVisual();
164    }
165
166    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
167    {
168      base.OnRenderSizeChanged(sizeInfo);
169      CreateRenderTask(Viewport.Visible, new Rect(sizeInfo.NewSize));
170      InvalidateVisual();
171    }
172
173    protected abstract BitmapSource RenderFrame(DataRect visible, Rect output);
174
175    private void RenderThreadFunc()
176    {
177      WaitHandle[] events = new WaitHandle[] { renderRequested, shutdownRequested };
178      while (true)
179      {
180        lock (this)
181        {
182          activeRequest = null;
183          if (pendingRequest != null)
184          {
185            activeRequest = pendingRequest;
186            pendingRequest = null;
187          }
188        }
189        if (activeRequest == null)
190        {
191          WaitHandle.WaitAny(events);
192          if (shutdownRequested.WaitOne(0))
193            break;
194        }
195        else
196        {
197          try
198          {
199            BitmapSource result = (BitmapSource)RenderFrame(activeRequest.Visible, activeRequest.Output);
200            if (result != null && !IsDisposed)
201              Dispatcher.BeginInvoke(
202                new RenderCompletionHandler(OnRenderCompleted),
203                new RenderResult(activeRequest, result));
204          }
205          catch (Exception exc)
206          {
207            Trace.WriteLine(String.Format("RenderRequest {0} failed: {1}", activeRequest.RequestID, exc.Message));
208          }
209        }
210      }
211    }
212
213    private void CreateRenderTask(DataRect visible, Rect output)
214    {
215      lock (this)
216      {
217        bitmapInvalidated = true;
218
219        if (activeRequest != null)
220          activeRequest.Cancel();
221        pendingRequest = new RenderRequest(nextRequestId++, visible, output);
222        renderRequested.Set();
223      }
224      if (renderThread == null)
225      {
226        renderThread = new Thread(RenderThreadFunc);
227        renderThread.IsBackground = true;
228        renderThread.SetApartmentState(ApartmentState.STA);
229        renderThread.Start();
230      }
231    }
232
233    private delegate void RenderCompletionHandler(RenderResult result);
234
235    protected virtual void OnRenderCompleted(RenderResult result)
236    {
237            if (IsDisposed)
238                return;
239
240      completedRequest = result.Request;
241      completedBitmap = result.Bitmap;
242      bitmapInvalidated = false;
243
244      InvalidateVisual();
245      BackgroundRenderer.RaiseRenderingFinished(this);
246    }
247
248    protected override void OnRenderCore(DrawingContext dc, RenderState state)
249    {
250      if (completedRequest != null && completedBitmap != null)
251        dc.DrawImage(completedBitmap, completedRequest.Visible.ViewportToScreen(Viewport.Transform));
252    }
253
254        public bool IsDisposed
255        {
256            get
257            {
258                return disposed > 0;
259            }
260        }
261
262        #region IDisposable Members
263
264        public void Dispose()
265        {
266            Interlocked.Increment(ref disposed);
267            shutdownRequested.Set();
268        }
269
270        #endregion
271    }
272
273  public class RenderRequest
274  {
275    private int requestId;
276    private DataRect visible;
277    private Rect output;
278    private int cancelling;
279
280    public RenderRequest(int requestId, DataRect visible, Rect output)
281    {
282      this.requestId = requestId;
283      this.visible = visible;
284      this.output = output;
285    }
286
287    public int RequestID
288    {
289      get { return requestId; }
290    }
291
292    public DataRect Visible
293    {
294      get { return visible; }
295    }
296
297    public Rect Output
298    {
299      get { return output; }
300    }
301
302    public bool IsCancellingRequested
303    {
304      get { return cancelling > 0; }
305    }
306
307    public void Cancel()
308    {
309      Interlocked.Increment(ref cancelling);
310    }
311  }
312
313  public class RenderResult
314  {
315    private RenderRequest request;
316        private BitmapSource bitmap;
317
318    /// <summary>Constructs successul rendering result</summary>
319    /// <param name="request">Source request</param>
320    /// <param name="result">Rendered bitmap</param>
321    public RenderResult(RenderRequest request, BitmapSource result)
322    {
323            this.bitmap = result;
324      this.request = request;
325            result.Freeze();
326    }
327
328    public RenderRequest Request
329    {
330      get { return request; }
331    }
332
333        public BitmapSource Bitmap
334        {
335            get { return bitmap; }
336        }
337  }
338}
Note: See TracBrowser for help on using the repository browser.