5
// Eric Maupin <ermau@xamarin.com>
7
// Copyright (c) 2012 Xamarin, Inc.
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
using System.Collections.Generic;
31
using System.Windows.Media;
32
using System.Windows.Media.Imaging;
34
using SWC = System.Windows.Controls;
36
using PixelFormat = System.Drawing.Imaging.PixelFormat;
38
namespace Xwt.WPFBackend
40
public class CanvasBackend
41
: WidgetBackend, ICanvasBackend
43
public CanvasBackend ()
45
Canvas = new ExCanvas();
46
Canvas.Render += OnRender;
48
this.image = new SWC.Image();
49
SWC.Panel.SetZIndex (this.image, -1);
51
Canvas.Children.Add (this.image);
54
public void QueueDraw()
56
this.fullRedraw = true;
59
Toolkit.QueueExitAction (Render);
64
public void QueueDraw (Rectangle rect)
69
this.dirtyRects.Add (rect.ToInt32Rect());
72
Toolkit.QueueExitAction (Render);
77
public void AddChild (IWidgetBackend widget, Rectangle bounds)
79
UIElement element = widget.NativeWidget as UIElement;
81
throw new ArgumentException();
83
if (!Canvas.Children.Contains (element))
84
Canvas.Children.Add (element);
86
SetChildBounds (widget, bounds);
89
public void SetChildBounds (IWidgetBackend widget, Rectangle bounds)
91
FrameworkElement element = widget.NativeWidget as FrameworkElement;
93
throw new ArgumentException();
95
double hratio = HeightPixelRatio;
96
double wratio = WidthPixelRatio;
98
SWC.Canvas.SetTop (element, bounds.Top * hratio);
99
SWC.Canvas.SetLeft (element, bounds.Left * wratio);
101
// We substract the widget margin here because the size we are assigning is the actual size, not including the WPF marings
102
var h = bounds.Height - ((WidgetBackend)widget).Frontend.Margin.VerticalSpacing;
103
var w = bounds.Width - ((WidgetBackend)widget).Frontend.Margin.HorizontalSpacing;
105
element.Height = (h > 0) ? h * hratio : 0;
106
element.Width = (w > 0) ? w * wratio : 0;
108
((FrameworkElement) widget.NativeWidget).UpdateLayout();
111
public void RemoveChild (IWidgetBackend widget)
113
UIElement element = widget.NativeWidget as UIElement;
115
throw new ArgumentException();
117
Canvas.Children.Remove (element);
121
private bool fullRedraw;
123
private readonly SWC.Image image;
124
private WriteableBitmap wbitmap;
125
private Bitmap bbitmap;
126
private readonly List<Int32Rect> dirtyRects = new List<Int32Rect> ();
128
private double pwidth = -1;
129
private double pheight = -1;
131
private ExCanvas Canvas
133
get { return (ExCanvas) Widget; }
134
set { Widget = value; }
137
private ICanvasEventSink CanvasEventSink
139
get { return (ICanvasEventSink) EventSink; }
142
private void OnRender (object sender, EventArgs e)
147
private void Render()
151
if (!Widget.IsVisible)
154
if (Canvas.ActualHeight != this.pheight || Canvas.ActualWidth != this.pwidth)
156
double heightRatio = HeightPixelRatio;
157
double widthRatio = WidthPixelRatio;
159
int nheight = (int) Math.Round (Canvas.ActualHeight * heightRatio) + 1;
160
int nwidth = (int) Math.Round (Canvas.ActualWidth * widthRatio) + 1;
162
if (nheight == 0 || nwidth == 0)
165
this.wbitmap = new WriteableBitmap (nwidth, nheight, widthRatio * 96, heightRatio * 96, PixelFormats.Pbgra32, null);
166
this.bbitmap = new Bitmap (nwidth, nheight, this.wbitmap.BackBufferStride, PixelFormat.Format32bppPArgb, this.wbitmap.BackBuffer);
167
this.image.Source = this.wbitmap;
169
this.pheight = Canvas.ActualHeight;
170
this.pwidth = Canvas.ActualWidth;
175
using (Graphics g = Graphics.FromImage (this.bbitmap))
176
CanvasEventSink.OnDraw (new DrawingContext (g), new Rectangle (0, 0, this.wbitmap.PixelWidth, this.wbitmap.PixelHeight));
178
if (this.fullRedraw || this.dirtyRects.Count == 0) {
179
this.wbitmap.AddDirtyRect (new Int32Rect (0, 0, this.wbitmap.PixelWidth, this.wbitmap.PixelHeight));
180
this.fullRedraw = false;
182
for (int i = 0; i < this.dirtyRects.Count; ++i) {
183
Int32Rect r = this.dirtyRects [i];
184
if (r.X >= this.wbitmap.PixelWidth || r.Y >= this.wbitmap.PixelHeight)
191
if (r.X + r.Width > this.wbitmap.PixelWidth)
192
r.Width = this.wbitmap.PixelWidth - r.X;
193
if (r.Y + r.Height > this.wbitmap.PixelHeight)
194
r.Height = this.wbitmap.PixelHeight - r.Y;
196
this.wbitmap.AddDirtyRect (r);
200
this.dirtyRects.Clear();
201
this.wbitmap.Unlock();
b'\\ No newline at end of file'