1 //
2 // LassoSelectTool.cs
3 //
4 // Author:
5 //       Jonathan Pobst <monkey@jpobst.com>
6 //
7 // Copyright (c) 2010 Jonathan Pobst
8 //
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:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
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
25 // THE SOFTWARE.
26 
27 using System;
28 using Cairo;
29 using Gtk;
30 using Pinta.Core;
31 using Mono.Unix;
32 using ClipperLibrary;
33 using System.Collections.Generic;
34 using System.Linq;
35 
36 namespace Pinta.Tools
37 {
38 	public class LassoSelectTool : BaseTool
39 	{
40 		private bool is_drawing = false;
41 		private CombineMode combine_mode;
42 		private SelectionHistoryItem hist;
43 
44 		private Path path;
45 		private List<IntPoint> lasso_polygon = new List<IntPoint>();
46 
LassoSelectTool()47 		public LassoSelectTool ()
48 		{
49 		}
50 
51 		#region Properties
52 		public override string Name { get { return Catalog.GetString ("Lasso Select"); } }
53 		public override string Icon { get { return "Tools.LassoSelect.png"; } }
54 		public override string StatusBarText { get { return Catalog.GetString ("Click and drag to draw the outline for a selection area."); } }
55 		public override Gdk.Key ShortcutKey { get { return Gdk.Key.S; } }
56 		public override Gdk.Cursor DefaultCursor { get { return new Gdk.Cursor (Gdk.Display.Default, PintaCore.Resources.GetIcon ("Cursor.LassoSelect.png"), 9, 18); } }
57 		public override int Priority { get { return 9; } }
58 		#endregion
59 
OnBuildToolBar(Toolbar tb)60 		protected override void OnBuildToolBar (Toolbar tb)
61 		{
62 			base.OnBuildToolBar (tb);
63 			PintaCore.Workspace.SelectionHandler.BuildToolbar (tb);
64 		}
65 
66 		#region Mouse Handlers
OnMouseDown(Gtk.DrawingArea canvas, Gtk.ButtonPressEventArgs args, Cairo.PointD point)67 		protected override void OnMouseDown (Gtk.DrawingArea canvas, Gtk.ButtonPressEventArgs args, Cairo.PointD point)
68 		{
69 			if (is_drawing)
70 				return;
71 
72 			hist = new SelectionHistoryItem (Icon, Name);
73 			hist.TakeSnapshot ();
74 
75 			combine_mode = PintaCore.Workspace.SelectionHandler.DetermineCombineMode (args);
76 			path = null;
77 			is_drawing = true;
78 
79 			var doc = PintaCore.Workspace.ActiveDocument;
80 			doc.PreviousSelection.Dispose ();
81 			doc.PreviousSelection = doc.Selection.Clone();
82 		}
83 
OnMouseMove(object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point)84 		protected override void OnMouseMove (object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point)
85 		{
86 			Document doc = PintaCore.Workspace.ActiveDocument;
87 
88 			if (!is_drawing)
89 				return;
90 
91 			double x = Utility.Clamp (point.X, 0, doc.ImageSize.Width - 1);
92 			double y = Utility.Clamp (point.Y, 0, doc.ImageSize.Height - 1);
93 
94 			doc.Selection.Visible = true;
95 
96 			ImageSurface surf = doc.SelectionLayer.Surface;
97 
98 			using (Context g = new Context (surf)) {
99 				g.Antialias = Antialias.Subpixel;
100 
101 				if (path != null) {
102 					g.AppendPath (path);
103 					(path as IDisposable).Dispose ();
104 				} else {
105 					g.MoveTo (x, y);
106 				}
107 
108 				g.LineTo (x, y);
109 				lasso_polygon.Add(new IntPoint((long)x, (long)y));
110 
111 				path = g.CopyPath ();
112 
113 				g.FillRule = FillRule.EvenOdd;
114 				g.ClosePath ();
115 			}
116 
117 			doc.Selection.SelectionPolygons.Clear ();
118 			doc.Selection.SelectionPolygons.Add (lasso_polygon.ToList ());
119 		    SelectionModeHandler.PerformSelectionMode (combine_mode, doc.Selection.SelectionPolygons);
120 			doc.Workspace.Invalidate ();
121 		}
122 
OnMouseUp(Gtk.DrawingArea canvas, Gtk.ButtonReleaseEventArgs args, Cairo.PointD point)123 		protected override void OnMouseUp (Gtk.DrawingArea canvas, Gtk.ButtonReleaseEventArgs args, Cairo.PointD point)
124 		{
125 			Document doc = PintaCore.Workspace.ActiveDocument;
126 
127 			ImageSurface surf = doc.SelectionLayer.Surface;
128 
129 			using (Context g = new Context (surf)) {
130 				if (path != null) {
131 					g.AppendPath (path);
132 					(path as IDisposable).Dispose ();
133 					path = null;
134 				}
135 
136 				g.FillRule = FillRule.EvenOdd;
137 				g.ClosePath ();
138 			}
139 
140 			doc.Selection.SelectionPolygons.Clear ();
141 			doc.Selection.SelectionPolygons.Add(lasso_polygon.ToList());
142 		    SelectionModeHandler.PerformSelectionMode (combine_mode, doc.Selection.SelectionPolygons);
143 			doc.Workspace.Invalidate ();
144 
145 			if (hist != null)
146 			{
147 				doc.History.PushNewItem (hist);
148 				hist = null;
149 			}
150 
151 			lasso_polygon.Clear();
152 			is_drawing = false;
153 		}
154 		#endregion
155 	}
156 }
157