5
// Lluis Sanchez <lluis@xamarin.com>
7
// Copyright (c) 2011 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;
32
using Xwt.CairoBackend;
34
namespace Xwt.GtkBackend
36
public class CanvasBackend: WidgetBackend, ICanvasBackend
38
public CanvasBackend ()
42
public override void Initialize ()
44
Widget = new CustomCanvas ();
45
Widget.Frontend = Frontend;
46
Widget.EventSink = EventSink;
47
Widget.Events |= Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask;
51
new CustomCanvas Widget {
52
get { return (CustomCanvas)base.Widget; }
53
set { base.Widget = value; }
56
protected new ICanvasEventSink EventSink {
57
get { return (ICanvasEventSink)base.EventSink; }
60
public void QueueDraw ()
65
public void QueueDraw (Rectangle rect)
67
Widget.QueueDrawArea ((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
70
public Rectangle Bounds {
72
return new Rectangle (0, 0, Widget.Allocation.Width, Widget.Allocation.Height);
76
public void AddChild (IWidgetBackend widget, Rectangle bounds)
78
var w = ((IGtkWidgetBackend)widget).Widget;
80
Widget.SetAllocation (w, bounds);
83
public void RemoveChild (IWidgetBackend widget)
85
var w = ((IGtkWidgetBackend)widget).Widget;
89
public void SetChildBounds (IWidgetBackend widget, Rectangle bounds)
91
var w = ((IGtkWidgetBackend)widget).Widget;
92
Widget.SetAllocation (w, bounds);
96
class CustomCanvas: Gtk.EventBox
98
public Widget Frontend;
99
public ICanvasEventSink EventSink;
100
Dictionary<Gtk.Widget, Rectangle> children = new Dictionary<Gtk.Widget, Rectangle> ();
102
public CustomCanvas ()
104
GtkWorkarounds.FixContainerLeak (this);
106
WidgetFlags |= Gtk.WidgetFlags.AppPaintable;
109
public void SetAllocation (Gtk.Widget w, Rectangle rect)
115
protected override void OnAdded (Gtk.Widget widget)
117
children.Add (widget, new Rectangle (0,0,0,0));
118
widget.Parent = this;
122
protected override void OnRemoved (Gtk.Widget widget)
124
children.Remove (widget);
128
protected override void OnSizeRequested (ref Gtk.Requisition requisition)
130
base.OnSizeRequested (ref requisition);
131
IWidgetSurface ws = Frontend.Surface;
133
if (ws.SizeRequestMode == SizeRequestMode.HeightForWidth) {
134
w = (int)ws.GetPreferredWidth ().MinSize;
135
h = (int)ws.GetPreferredHeightForWidth (w).MinSize;
137
h = (int)ws.GetPreferredHeight ().MinSize;
138
w = (int)ws.GetPreferredWidthForHeight(h).MinSize;
140
if (requisition.Width < w)
141
requisition.Width = w;
142
if (requisition.Height < h)
143
requisition.Height = h;
144
foreach (var cr in children)
145
cr.Key.SizeRequest ();
148
protected override void OnUnrealized ()
150
base.OnUnrealized ();
151
lastAllocation = new Gdk.Rectangle ();
154
Gdk.Rectangle lastAllocation;
156
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
158
base.OnSizeAllocated (allocation);
159
if (!lastAllocation.Equals (allocation))
160
((IWidgetSurface)Frontend).Reallocate ();
161
lastAllocation = allocation;
162
foreach (var cr in children) {
164
cr.Key.SizeAllocate (new Gdk.Rectangle ((int)r.X, (int)r.Y, (int)r.Width, (int)r.Height));
168
protected override void ForAll (bool includeInternals, Gtk.Callback callback)
170
base.ForAll (includeInternals, callback);
171
foreach (var c in children.Keys.ToArray ())
175
protected override bool OnExposeEvent (Gdk.EventExpose evnt)
177
Toolkit.Invoke (delegate {
178
using (var context = CreateContext ()) {
180
EventSink.OnDraw (context, new Rectangle (a.X, a.Y, a.Width, a.Height));
183
return base.OnExposeEvent (evnt);
186
public CairoContextBackend CreateContext ()
188
CairoContextBackend ctx = new CairoContextBackend ();
190
Cairo.Surface sf = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1);
191
Cairo.Context c = new Cairo.Context (sf);
193
ctx.TempSurface = sf;
195
ctx.Context = Gdk.CairoHelper.Create (GdkWindow);