1 //
2 // LayerActions.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 Gdk;
29 using Gtk;
30 using Mono.Unix;
31 using System.IO;
32 
33 namespace Pinta.Core
34 {
35 	public class LayerActions
36 	{
37 		public Gtk.Action AddNewLayer { get; private set; }
38 		public Gtk.Action DeleteLayer { get; private set; }
39 		public Gtk.Action DuplicateLayer { get; private set; }
40 		public Gtk.Action MergeLayerDown { get; private set; }
41 		public Gtk.Action ImportFromFile { get; private set; }
42 		public Gtk.Action FlipHorizontal { get; private set; }
43 		public Gtk.Action FlipVertical { get; private set; }
44 		public Gtk.Action RotateZoom { get; private set; }
45 		public Gtk.Action MoveLayerUp { get; private set; }
46 		public Gtk.Action MoveLayerDown { get; private set; }
47 		public Gtk.Action Properties { get; private set; }
48 
LayerActions()49 		public LayerActions ()
50 		{
51 			Gtk.IconFactory fact = new Gtk.IconFactory ();
52 			fact.Add ("Menu.Layers.AddNewLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.AddNewLayer.png")));
53 			fact.Add ("Menu.Layers.DeleteLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.DeleteLayer.png")));
54 			fact.Add ("Menu.Layers.DuplicateLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.DuplicateLayer.png")));
55 			fact.Add ("Menu.Layers.MergeLayerDown.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MergeLayerDown.png")));
56 			fact.Add ("Menu.Layers.MoveLayerDown.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MoveLayerDown.png")));
57 			fact.Add ("Menu.Layers.MoveLayerUp.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MoveLayerUp.png")));
58 			fact.Add ("Menu.Layers.FlipHorizontal.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.FlipHorizontal.png")));
59 			fact.Add ("Menu.Layers.FlipVertical.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.FlipVertical.png")));
60 			fact.Add ("Menu.Layers.ImportFromFile.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.ImportFromFile.png")));
61 			fact.Add ("Menu.Layers.LayerProperties.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.LayerProperties.png")));
62 			fact.Add ("Menu.Layers.RotateZoom.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.RotateZoom.png")));
63 			fact.AddDefault ();
64 
65 			AddNewLayer = new Gtk.Action ("AddNewLayer", Catalog.GetString ("Add New Layer"), null, "Menu.Layers.AddNewLayer.png");
66 			DeleteLayer = new Gtk.Action ("DeleteLayer", Catalog.GetString ("Delete Layer"), null, "Menu.Layers.DeleteLayer.png");
67 			DuplicateLayer = new Gtk.Action ("DuplicateLayer", Catalog.GetString ("Duplicate Layer"), null, "Menu.Layers.DuplicateLayer.png");
68 			MergeLayerDown = new Gtk.Action ("MergeLayerDown", Catalog.GetString ("Merge Layer Down"), null, "Menu.Layers.MergeLayerDown.png");
69 			ImportFromFile = new Gtk.Action ("ImportFromFile", Catalog.GetString ("Import from File..."), null, "Menu.Layers.ImportFromFile.png");
70 			FlipHorizontal = new Gtk.Action ("FlipHorizontal", Catalog.GetString ("Flip Horizontal"), null, "Menu.Layers.FlipHorizontal.png");
71 			FlipVertical = new Gtk.Action ("FlipVertical", Catalog.GetString ("Flip Vertical"), null, "Menu.Layers.FlipVertical.png");
72 			RotateZoom = new Gtk.Action ("RotateZoom", Catalog.GetString ("Rotate / Zoom Layer..."), null, "Menu.Layers.RotateZoom.png");
73 			MoveLayerUp = new Gtk.Action ("MoveLayerUp", Catalog.GetString ("Move Layer Up"), null, "Menu.Layers.MoveLayerUp.png");
74 			MoveLayerDown = new Gtk.Action ("MoveLayerDown", Catalog.GetString ("Move Layer Down"), null, "Menu.Layers.MoveLayerDown.png");
75 			Properties = new Gtk.Action ("Properties", Catalog.GetString ("Layer Properties..."), null, "Menu.Layers.LayerProperties.png");
76 
77 			RotateZoom.Sensitive = false;
78 		}
79 
80 		#region Initialization
CreateMainMenu(Gtk.Menu menu)81 		public void CreateMainMenu (Gtk.Menu menu)
82 		{
83 			menu.Append (AddNewLayer.CreateAcceleratedMenuItem (Gdk.Key.N, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask));
84 			menu.Append (DeleteLayer.CreateAcceleratedMenuItem (Gdk.Key.Delete, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask));
85 			menu.Append (DuplicateLayer.CreateAcceleratedMenuItem (Gdk.Key.D, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask));
86 			menu.Append (MergeLayerDown.CreateAcceleratedMenuItem (Gdk.Key.M, Gdk.ModifierType.ControlMask));
87 			menu.Append (ImportFromFile.CreateMenuItem ());
88 			menu.AppendSeparator ();
89 			menu.Append (FlipHorizontal.CreateMenuItem ());
90 			menu.Append (FlipVertical.CreateMenuItem ());
91 			menu.Append (RotateZoom.CreateMenuItem ());
92 			menu.AppendSeparator ();
93 			menu.Append (Properties.CreateAcceleratedMenuItem (Gdk.Key.F4, Gdk.ModifierType.None));
94 		}
95 
CreateLayerWindowToolBar(Gtk.Toolbar toolbar)96 		public void CreateLayerWindowToolBar (Gtk.Toolbar toolbar)
97 		{
98 			toolbar.AppendItem (AddNewLayer.CreateToolBarItem ());
99 			toolbar.AppendItem (DeleteLayer.CreateToolBarItem ());
100 			toolbar.AppendItem (DuplicateLayer.CreateToolBarItem ());
101 			toolbar.AppendItem (MergeLayerDown.CreateToolBarItem ());
102 			toolbar.AppendItem (MoveLayerUp.CreateToolBarItem ());
103 			toolbar.AppendItem (MoveLayerDown.CreateToolBarItem ());
104 			toolbar.AppendItem (Properties.CreateToolBarItem ());
105 		}
106 
RegisterHandlers()107 		public void RegisterHandlers ()
108 		{
109 			AddNewLayer.Activated += HandlePintaCoreActionsLayersAddNewLayerActivated;
110 			DeleteLayer.Activated += HandlePintaCoreActionsLayersDeleteLayerActivated;
111 			DuplicateLayer.Activated += HandlePintaCoreActionsLayersDuplicateLayerActivated;
112 			MergeLayerDown.Activated += HandlePintaCoreActionsLayersMergeLayerDownActivated;
113 			MoveLayerDown.Activated += HandlePintaCoreActionsLayersMoveLayerDownActivated;
114 			MoveLayerUp.Activated += HandlePintaCoreActionsLayersMoveLayerUpActivated;
115 			FlipHorizontal.Activated += HandlePintaCoreActionsLayersFlipHorizontalActivated;
116 			FlipVertical.Activated += HandlePintaCoreActionsLayersFlipVerticalActivated;
117 			ImportFromFile.Activated += HandlePintaCoreActionsLayersImportFromFileActivated;
118 
119 			PintaCore.Layers.LayerAdded += EnableOrDisableLayerActions;
120 			PintaCore.Layers.LayerRemoved += EnableOrDisableLayerActions;
121 			PintaCore.Layers.SelectedLayerChanged += EnableOrDisableLayerActions;
122 
123 			EnableOrDisableLayerActions (null, EventArgs.Empty);
124 		}
125 		#endregion
126 
127 		#region Action Handlers
EnableOrDisableLayerActions(object sender, EventArgs e)128 		private void EnableOrDisableLayerActions (object sender, EventArgs e)
129 		{
130 			if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.UserLayers.Count > 1) {
131 				PintaCore.Actions.Layers.DeleteLayer.Sensitive = true;
132 				PintaCore.Actions.Image.Flatten.Sensitive = true;
133 			} else {
134 				PintaCore.Actions.Layers.DeleteLayer.Sensitive = false;
135 				PintaCore.Actions.Image.Flatten.Sensitive = false;
136 			}
137 
138 			if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.CurrentUserLayerIndex > 0) {
139 				PintaCore.Actions.Layers.MergeLayerDown.Sensitive = true;
140 				PintaCore.Actions.Layers.MoveLayerDown.Sensitive = true;
141 			} else {
142 				PintaCore.Actions.Layers.MergeLayerDown.Sensitive = false;
143 				PintaCore.Actions.Layers.MoveLayerDown.Sensitive = false;
144 			}
145 
146 			if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.CurrentUserLayerIndex < PintaCore.Workspace.ActiveDocument.UserLayers.Count - 1)
147 				PintaCore.Actions.Layers.MoveLayerUp.Sensitive = true;
148 			else
149 				PintaCore.Actions.Layers.MoveLayerUp.Sensitive = false;
150 		}
151 
HandlePintaCoreActionsLayersImportFromFileActivated(object sender, EventArgs e)152 		private void HandlePintaCoreActionsLayersImportFromFileActivated (object sender, EventArgs e)
153 		{
154 			Document doc = PintaCore.Workspace.ActiveDocument;
155 			PintaCore.Tools.Commit ();
156 
157 			var fcd = new Gtk.FileChooserDialog (Catalog.GetString ("Open Image File"),PintaCore.Chrome.MainWindow,
158 			                                     FileChooserAction.Open, Stock.Cancel, ResponseType.Cancel,
159 			                                     Stock.Open, ResponseType.Ok);
160 
161             		fcd.SetCurrentFolder (PintaCore.System.GetDialogDirectory ());
162 			fcd.AlternativeButtonOrder = new int[] { (int) ResponseType.Ok, (int) ResponseType.Cancel };
163 
164 			fcd.AddImagePreview ();
165 
166 			int response = fcd.Run ();
167 
168 			if (response == (int)Gtk.ResponseType.Ok) {
169 
170 				string file = fcd.Filename;
171 				PintaCore.System.LastDialogDirectory = fcd.CurrentFolder;
172 
173 				// Open the image and add it to the layers
174 				UserLayer layer = doc.AddNewLayer(System.IO.Path.GetFileName(file));
175 
176 				using (var fs = new FileStream (file, FileMode.Open))
177 					using (Pixbuf bg = new Pixbuf (fs))
178 						using (Cairo.Context g = new Cairo.Context (layer.Surface)) {
179 							CairoHelper.SetSourcePixbuf (g, bg, 0, 0);
180 							g.Paint ();
181 						}
182 
183 				doc.SetCurrentUserLayer (layer);
184 
185 				AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.ImportFromFile.png", Catalog.GetString ("Import From File"), doc.UserLayers.IndexOf (layer));
186 				doc.History.PushNewItem (hist);
187 
188 				doc.Workspace.Invalidate ();
189 			}
190 
191 			fcd.Destroy ();
192 		}
193 
HandlePintaCoreActionsLayersFlipVerticalActivated(object sender, EventArgs e)194 		private void HandlePintaCoreActionsLayersFlipVerticalActivated (object sender, EventArgs e)
195 		{
196 			Document doc = PintaCore.Workspace.ActiveDocument;
197 			PintaCore.Tools.Commit ();
198 
199 			doc.CurrentUserLayer.FlipVertical ();
200 			doc.Workspace.Invalidate ();
201 			doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipLayerVertical, doc.CurrentUserLayerIndex));
202 		}
203 
HandlePintaCoreActionsLayersFlipHorizontalActivated(object sender, EventArgs e)204 		private void HandlePintaCoreActionsLayersFlipHorizontalActivated (object sender, EventArgs e)
205 		{
206 			Document doc = PintaCore.Workspace.ActiveDocument;
207 			PintaCore.Tools.Commit ();
208 
209 			doc.CurrentUserLayer.FlipHorizontal ();
210 			doc.Workspace.Invalidate ();
211 			doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipLayerHorizontal, doc.CurrentUserLayerIndex));
212 		}
213 
HandlePintaCoreActionsLayersMoveLayerUpActivated(object sender, EventArgs e)214 		private void HandlePintaCoreActionsLayersMoveLayerUpActivated (object sender, EventArgs e)
215 		{
216 			Document doc = PintaCore.Workspace.ActiveDocument;
217 			PintaCore.Tools.Commit ();
218 
219 			SwapLayersHistoryItem hist = new SwapLayersHistoryItem ("Menu.Layers.MoveLayerUp.png", Catalog.GetString ("Move Layer Up"), doc.CurrentUserLayerIndex, doc.CurrentUserLayerIndex + 1);
220 
221 			doc.MoveCurrentLayerUp ();
222 			doc.History.PushNewItem (hist);
223 		}
224 
HandlePintaCoreActionsLayersMoveLayerDownActivated(object sender, EventArgs e)225 		private void HandlePintaCoreActionsLayersMoveLayerDownActivated (object sender, EventArgs e)
226 		{
227 			Document doc = PintaCore.Workspace.ActiveDocument;
228 			PintaCore.Tools.Commit ();
229 
230 			SwapLayersHistoryItem hist = new SwapLayersHistoryItem ("Menu.Layers.MoveLayerDown.png", Catalog.GetString ("Move Layer Down"), doc.CurrentUserLayerIndex, doc.CurrentUserLayerIndex - 1);
231 
232 			doc.MoveCurrentLayerDown ();
233 			doc.History.PushNewItem (hist);
234 		}
235 
HandlePintaCoreActionsLayersMergeLayerDownActivated(object sender, EventArgs e)236 		private void HandlePintaCoreActionsLayersMergeLayerDownActivated (object sender, EventArgs e)
237 		{
238 			Document doc = PintaCore.Workspace.ActiveDocument;
239 			PintaCore.Tools.Commit ();
240 
241 			int bottomLayerIndex = doc.CurrentUserLayerIndex - 1;
242 			var oldBottomSurface = doc.UserLayers[bottomLayerIndex].Surface.Clone ();
243 
244 			CompoundHistoryItem hist = new CompoundHistoryItem ("Menu.Layers.MergeLayerDown.png", Catalog.GetString ("Merge Layer Down"));
245 			DeleteLayerHistoryItem h1 = new DeleteLayerHistoryItem (string.Empty, string.Empty, doc.CurrentUserLayer, doc.CurrentUserLayerIndex);
246 
247 			doc.MergeCurrentLayerDown ();
248 
249 			SimpleHistoryItem h2 = new SimpleHistoryItem (string.Empty, string.Empty, oldBottomSurface, bottomLayerIndex);
250 			hist.Push (h1);
251 			hist.Push (h2);
252 
253 			doc.History.PushNewItem (hist);
254 		}
255 
HandlePintaCoreActionsLayersDuplicateLayerActivated(object sender, EventArgs e)256 		private void HandlePintaCoreActionsLayersDuplicateLayerActivated (object sender, EventArgs e)
257 		{
258 			Document doc = PintaCore.Workspace.ActiveDocument;
259 			PintaCore.Tools.Commit ();
260 
261 			UserLayer l = doc.DuplicateCurrentLayer();
262 
263 			// Make new layer the current layer
264 			doc.SetCurrentUserLayer (l);
265 
266 			AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.DuplicateLayer.png", Catalog.GetString ("Duplicate Layer"), doc.UserLayers.IndexOf (l));
267 			doc.History.PushNewItem (hist);
268 		}
269 
HandlePintaCoreActionsLayersDeleteLayerActivated(object sender, EventArgs e)270 		private void HandlePintaCoreActionsLayersDeleteLayerActivated (object sender, EventArgs e)
271 		{
272 			Document doc = PintaCore.Workspace.ActiveDocument;
273 			PintaCore.Tools.Commit ();
274 
275 			DeleteLayerHistoryItem hist = new DeleteLayerHistoryItem ("Menu.Layers.DeleteLayer.png", Catalog.GetString ("Delete Layer"), doc.CurrentUserLayer, doc.CurrentUserLayerIndex);
276 
277 			doc.DeleteLayer (doc.CurrentUserLayerIndex, false);
278 
279 			doc.History.PushNewItem (hist);
280 		}
281 
HandlePintaCoreActionsLayersAddNewLayerActivated(object sender, EventArgs e)282 		private void HandlePintaCoreActionsLayersAddNewLayerActivated (object sender, EventArgs e)
283 		{
284 			Document doc = PintaCore.Workspace.ActiveDocument;
285 			PintaCore.Tools.Commit ();
286 
287 			UserLayer l = doc.AddNewLayer(string.Empty);
288 
289 			// Make new layer the current layer
290 			doc.SetCurrentUserLayer (l);
291 
292 			AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.AddNewLayer.png", Catalog.GetString ("Add New Layer"), doc.UserLayers.IndexOf (l));
293 			doc.History.PushNewItem (hist);
294 		}
295 		#endregion
296 	}
297 }
298