PintaCanvas.cs (pinta-1.7) | : | PintaCanvas.cs (pinta-1.7.1) | ||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
// | // | |||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
// THE SOFTWARE. | // THE SOFTWARE. | |||
using System; | using System; | |||
using System.Linq; | ||||
using Gdk; | using Gdk; | |||
using Gtk; | using Gtk; | |||
using Pinta.Core; | using Pinta.Core; | |||
namespace Pinta.Gui.Widgets | namespace Pinta.Gui.Widgets | |||
{ | { | |||
[System.ComponentModel.ToolboxItem (true)] | [System.ComponentModel.ToolboxItem (true)] | |||
public class PintaCanvas : DrawingArea | public class PintaCanvas : DrawingArea | |||
{ | { | |||
Cairo.ImageSurface canvas; | Cairo.ImageSurface canvas; | |||
CanvasRenderer cr; | CanvasRenderer cr; | |||
private Document document; | private Document document; | |||
private int hScrollAmount = 92; | ||||
public CanvasWindow CanvasWindow { get; private set; } | public CanvasWindow CanvasWindow { get; private set; } | |||
public PintaCanvas (CanvasWindow window, Document document) | public PintaCanvas (CanvasWindow window, Document document) | |||
{ | { | |||
CanvasWindow = window; | CanvasWindow = window; | |||
this.document = document; | this.document = document; | |||
cr = new CanvasRenderer (true); | cr = new CanvasRenderer (true); | |||
// Keep the widget the same size as the canvas | // Keep the widget the same size as the canvas | |||
document.Workspace.CanvasSizeChanged += delegate (object sender, Eve | document.Workspace.CanvasSizeChanged += delegate (object | |||
ntArgs e) { | sender, EventArgs e) { | |||
SetRequisition (document.Workspace.CanvasSize); | SetRequisition (document.Workspace.CanvasSize); | |||
}; | }; | |||
// Update the canvas when the image changes | // Update the canvas when the image changes | |||
document.Workspace.CanvasInvalidated += delegate (object sender, Can | document.Workspace.CanvasInvalidated += delegate (object | |||
vasInvalidatedEventArgs e) { | sender, CanvasInvalidatedEventArgs e) { | |||
// If GTK+ hasn't created the canvas window yet, no need to inva | // If GTK+ hasn't created the canvas window yet, | |||
lidate it | no need to invalidate it | |||
if (GdkWindow == null) | if (GdkWindow == null) | |||
return; | return; | |||
if (e.EntireSurface) | if (e.EntireSurface) | |||
GdkWindow.Invalidate (); | GdkWindow.Invalidate (); | |||
else | else | |||
GdkWindow.InvalidateRect (e.Rectangle, fa lse); | GdkWindow.InvalidateRect (e.Rectangle, fa lse); | |||
}; | }; | |||
// Give mouse press events to the current tool | // Give mouse press events to the current tool | |||
ButtonPressEvent += delegate (object sender, ButtonPressE ventArgs e) { | ButtonPressEvent += delegate (object sender, ButtonPressE ventArgs e) { | |||
// The canvas gets the button press before the tab system, so | // The canvas gets the button press before the ta | |||
// if this click is on a canvas that isn't currently the ActiveD | b system, so | |||
ocument yet, | // if this click is on a canvas that isn't curren | |||
// we need to go ahead and make it the active document for the t | tly the ActiveDocument yet, | |||
ools | // we need to go ahead and make it the active doc | |||
// to use it, even though right after this the tab system would | ument for the tools | |||
have switched it | // to use it, even though right after this the ta | |||
if (PintaCore.Workspace.ActiveDocument != document) | b system would have switched it | |||
PintaCore.Workspace.SetActiveDocument (document); | if (PintaCore.Workspace.ActiveDocument != documen | |||
t) | ||||
PintaCore.Workspace.SetActiveDocument (do | ||||
cument); | ||||
PintaCore.Tools.CurrentTool.DoMouseDown (this, e, document.Works pace.WindowPointToCanvas (e.Event.X, e.Event.Y)); | PintaCore.Tools.CurrentTool.DoMouseDown (this, e, document.Workspace.WindowPointToCanvas (e.Event.X, e.Event.Y)); | |||
}; | }; | |||
// Give mouse release events to the current tool | // Give mouse release events to the current tool | |||
ButtonReleaseEvent += delegate (object sender, ButtonRele aseEventArgs e) { | ButtonReleaseEvent += delegate (object sender, ButtonRele aseEventArgs e) { | |||
PintaCore.Tools.CurrentTool.DoMouseUp (this, e, document.Workspa ce.WindowPointToCanvas (e.Event.X, e.Event.Y)); | PintaCore.Tools.CurrentTool.DoMouseUp (this, e, d ocument.Workspace.WindowPointToCanvas (e.Event.X, e.Event.Y)); | |||
}; | }; | |||
// Give mouse move events to the current tool | // Give mouse move events to the current tool | |||
MotionNotifyEvent += delegate (object sender, MotionNotif yEventArgs e) { | MotionNotifyEvent += delegate (object sender, MotionNotif yEventArgs e) { | |||
var point = document.Workspace.WindowPointToCanvas (e.Event.X, e .Event.Y); | var point = document.Workspace.WindowPointToCanva s (e.Event.X, e.Event.Y); | |||
if (document.Workspace.PointInCanvas (point)) | if (document.Workspace.PointInCanvas (point)) | |||
PintaCore.Chrome.LastCanvasCursorPoint = point.ToGdkPoint (); | PintaCore.Chrome.LastCanvasCursorPoint = point.ToGdkPoint (); | |||
if (PintaCore.Tools.CurrentTool != null) | if (PintaCore.Tools.CurrentTool != null) | |||
PintaCore.Tools.CurrentTool.DoMouseMove ( (DrawingArea)sender, e, point); | PintaCore.Tools.CurrentTool.DoMouseMove ( (DrawingArea)sender, e, point); | |||
}; | }; | |||
} | } | |||
#region Protected Methods | #region Protected Methods | |||
protected override bool OnExposeEvent (EventExpose e) | protected override bool OnExposeEvent (EventExpose e) | |||
{ | { | |||
base.OnExposeEvent (e); | base.OnExposeEvent (e); | |||
var scale = document.Workspace.Scale; | var scale = document.Workspace.Scale; | |||
var x = (int)document.Workspace.Offset.X; | var x = (int)document.Workspace.Offset.X; | |||
var y = (int)document.Workspace.Offset.Y; | var y = (int)document.Workspace.Offset.Y; | |||
// Translate our expose area for the whole drawingarea to just our canvas | // Translate our expose area for the whole drawingarea to just our canvas | |||
var canvas_bounds = new Rectangle (x, y, document.Workspace.CanvasSi ze.Width, document.Workspace.CanvasSize.Height); | var canvas_bounds = new Rectangle (x, y, document.Workspa ce.CanvasSize.Width, document.Workspace.CanvasSize.Height); | |||
canvas_bounds.Intersect (e.Area); | canvas_bounds.Intersect (e.Area); | |||
if (canvas_bounds.IsEmpty) | if (canvas_bounds.IsEmpty) | |||
return true; | return true; | |||
canvas_bounds.X -= x; | canvas_bounds.X -= x; | |||
canvas_bounds.Y -= y; | canvas_bounds.Y -= y; | |||
// Resize our offscreen surface to a surface the size of our drawing area | // Resize our offscreen surface to a surface the size of our drawing area | |||
if (canvas == null || canvas.Width != canvas_bounds.Width || canvas.Height != canvas_bounds.Height) { | if (canvas == null || canvas.Width != canvas_bounds.Width || canvas.Height != canvas_bounds.Height) { | |||
if (canvas != null) | if (canvas != null) | |||
(canvas as IDisposable).Dispose (); | (canvas as IDisposable).Dispose (); | |||
canvas = new Cairo.ImageSurface (Cairo.Format.Arg b32, canvas_bounds.Width, canvas_bounds.Height); | canvas = CairoExtensions.CreateImageSurface (Cair o.Format.Argb32, canvas_bounds.Width, canvas_bounds.Height); | |||
} | } | |||
cr.Initialize (document.ImageSize, document.Workspace.CanvasSize); | cr.Initialize (document.ImageSize, document.Workspace.Can vasSize); | |||
using (var g = CairoHelper.Create (GdkWindow)) { | using (var g = CairoHelper.Create (GdkWindow)) { | |||
// Draw our canvas drop shadow | // Draw our canvas drop shadow | |||
g.DrawRectangle (new Cairo.Rectangle (x - 1, y - 1, document.Wor | g.DrawRectangle (new Cairo.Rectangle (x - 1, y - | |||
kspace.CanvasSize.Width + 2, document.Workspace.CanvasSize.Height + 2), new Cair | 1, document.Workspace.CanvasSize.Width + 2, document.Workspace.CanvasSize.Height | |||
o.Color (.5, .5, .5), 1); | + 2), new Cairo.Color (.5, .5, .5), 1); | |||
g.DrawRectangle (new Cairo.Rectangle (x - 2, y - 2, document.Wor | g.DrawRectangle (new Cairo.Rectangle (x - 2, y - | |||
kspace.CanvasSize.Width + 4, document.Workspace.CanvasSize.Height + 4), new Cair | 2, document.Workspace.CanvasSize.Width + 4, document.Workspace.CanvasSize.Height | |||
o.Color (.8, .8, .8), 1); | + 4), new Cairo.Color (.8, .8, .8), 1); | |||
g.DrawRectangle (new Cairo.Rectangle (x - 3, y - 3, document.Wor | g.DrawRectangle (new Cairo.Rectangle (x - 3, y - | |||
kspace.CanvasSize.Width + 6, document.Workspace.CanvasSize.Height + 6), new Cair | 3, document.Workspace.CanvasSize.Width + 6, document.Workspace.CanvasSize.Height | |||
o.Color (.9, .9, .9), 1); | + 6), new Cairo.Color (.9, .9, .9), 1); | |||
// Set up our clip rectangle | // Set up our clip rectangle | |||
g.Rectangle (new Cairo.Rectangle (x, y, document.Workspace.Canva sSize.Width, document.Workspace.CanvasSize.Height)); | g.Rectangle (new Cairo.Rectangle (x, y, document. Workspace.CanvasSize.Width, document.Workspace.CanvasSize.Height)); | |||
g.Clip (); | g.Clip (); | |||
g.Translate (x, y); | g.Translate (x, y); | |||
// Render all the layers to a surface | // Render all the layers to a surface | |||
var layers = document.GetLayersToPaint (); | var layers = document.GetLayersToPaint (); | |||
if (layers.Count == 0) | if (layers.Count == 0) | |||
canvas.Clear (); | canvas.Clear (); | |||
cr.Render (layers, canvas, canvas_bounds.Location ); | cr.Render (layers, canvas, canvas_bounds.Location ); | |||
// Paint the surface to our canvas | // Paint the surface to our canvas | |||
g.SetSourceSurface (canvas, canvas_bounds.X + (in t)(0 * scale), canvas_bounds.Y + (int)(0 * scale)); | g.SetSourceSurface (canvas, canvas_bounds.X + (in t)(0 * scale), canvas_bounds.Y + (int)(0 * scale)); | |||
g.Paint (); | g.Paint (); | |||
// Selection outline | // Selection outline | |||
if (document.Selection.Visible) { | if (document.Selection.Visible) { | |||
bool fillSelection = PintaCore.Tools.Curr | bool fillSelection = PintaCore.Tools.Curr | |||
entTool.Name.Contains ("Select") && | entTool.Name.Contains ("Select") && | |||
!PintaCore.Tools.CurrentTool.Name | !PintaCore.Tools.Cur | |||
.Contains ("Selected"); | rentTool.Name.Contains ("Selected"); | |||
document.Selection.Draw (g, scale, fillSelec | document.Selection.Draw (g, scale, fillSe | |||
tion); | lection); | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
protected override bool OnScrollEvent (EventScroll evnt) | protected override bool OnScrollEvent (EventScroll evnt) | |||
{ | { | |||
// Allow the user to zoom in/out with Ctrl-Mousewheel | // Allow the user to zoom in/out with Ctrl-Mousewheel | |||
if (evnt.State.FilterModifierKeys () == ModifierType.ControlMask) { | if (evnt.State.FilterModifierKeys () == ModifierType.Cont rolMask) { | |||
switch (evnt.Direction) { | switch (evnt.Direction) { | |||
case ScrollDirection.Down: | case ScrollDirection.Down: | |||
case ScrollDirection.Right: | case ScrollDirection.Right: | |||
document.Workspace.ZoomOutFromMouseScroll (new Cairo.Poi ntD (evnt.X, evnt.Y)); | document.Workspace.ZoomOutFromMou seScroll (new Cairo.PointD (evnt.X, evnt.Y)); | |||
return true; | return true; | |||
case ScrollDirection.Left: | case ScrollDirection.Left: | |||
case ScrollDirection.Up: | case ScrollDirection.Up: | |||
document.Workspace.ZoomInFromMouseScroll (new Cairo.Poin | document.Workspace.ZoomInFromMous | |||
tD (evnt.X, evnt.Y)); | eScroll (new Cairo.PointD (evnt.X, evnt.Y)); | |||
return true; | ||||
} | ||||
} | ||||
// Allow the user to scroll left/right with Shift-Mousewh | ||||
eel | ||||
if (evnt.State.FilterModifierKeys () == ModifierType.Shif | ||||
tMask) { | ||||
switch (evnt.Direction) { | ||||
case ScrollDirection.Down: | ||||
case ScrollDirection.Right: | ||||
document.Workspace.ScrollCanvas ( | ||||
hScrollAmount, 0); | ||||
return true; | ||||
case ScrollDirection.Up: | ||||
case ScrollDirection.Left: | ||||
document.Workspace.ScrollCanvas ( | ||||
-hScrollAmount, 0); | ||||
return true; | return true; | |||
} | } | |||
} | } | |||
return base.OnScrollEvent (evnt); | return base.OnScrollEvent (evnt); | |||
} | } | |||
#endregion | #endregion | |||
#region Private Methods | #region Private Methods | |||
private void SetRequisition (Size size) | private void SetRequisition (Size size) | |||
End of changes. 22 change blocks. | ||||
54 lines changed or deleted | 75 lines changed or added |