summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SpriteEd/AppDelegate.cs15
-rw-r--r--SpriteEd/NSSpriteEdit.cs75
-rw-r--r--SpriteEd/NSSpriteEditWindowDelegate.cs86
-rw-r--r--SpriteEd/Sprite.cs12
-rw-r--r--SpriteEd/SpriteEd.csproj1
-rw-r--r--SpriteEd/ViewController.cs22
6 files changed, 190 insertions, 21 deletions
diff --git a/SpriteEd/AppDelegate.cs b/SpriteEd/AppDelegate.cs
index eb40bd7..3756e70 100644
--- a/SpriteEd/AppDelegate.cs
+++ b/SpriteEd/AppDelegate.cs
@@ -38,6 +38,15 @@ namespace SpriteEd
// Insert code here to tear down your application
}
+ private ViewController ViewController
+ {
+ get
+ {
+ NSWindowController controller = NSApplication.SharedApplication.KeyWindow.WindowController as NSWindowController;
+ return controller.ContentViewController as ViewController;
+ }
+ }
+
[Export("newDocument:")]
private void OnNewDocument(NSObject sender)
{
@@ -46,8 +55,7 @@ namespace SpriteEd
[Export("saveDocumentAs:")]
private void OnSaveDocumentAs(NSObject sender)
{
- NSWindowController controller = NSApplication.SharedApplication.KeyWindow.WindowController as NSWindowController;
- ViewController view = controller.ContentViewController as ViewController;
+ ViewController view = ViewController;
NSSavePanel fsel = new NSSavePanel();
@@ -75,8 +83,7 @@ namespace SpriteEd
[Export("saveDocument:")]
private void OnSaveDocument(NSObject sender)
{
- NSWindowController controller = NSApplication.SharedApplication.KeyWindow.WindowController as NSWindowController;
- ViewController view = controller.ContentViewController as ViewController;
+ ViewController view = ViewController;
if (view.Untitled)
{
diff --git a/SpriteEd/NSSpriteEdit.cs b/SpriteEd/NSSpriteEdit.cs
index f6067ee..f5d5dc5 100644
--- a/SpriteEd/NSSpriteEdit.cs
+++ b/SpriteEd/NSSpriteEdit.cs
@@ -20,6 +20,7 @@ using Foundation;
using System.CodeDom.Compiler;
using AppKit;
using CoreGraphics;
+using System.Collections.Generic;
namespace SpriteEd
{
@@ -81,7 +82,7 @@ namespace SpriteEd
}
private Sprite m_sprite;
- private Sprite m_undo;
+ private Stack<Sprite> m_undo;
private uint m_sx;
private uint m_sy;
private uint m_ex;
@@ -95,7 +96,7 @@ namespace SpriteEd
set
{
m_sprite = value;
- m_undo = new Sprite(m_sprite.Width, m_sprite.Height);
+ ClearUndo();
NeedsDisplay = true;
}
}
@@ -157,8 +158,11 @@ namespace SpriteEd
/// </summary>
private void Init()
{
+ m_undo = new Stack<Sprite>();
m_sx = uint.MaxValue;
m_sy = uint.MaxValue;
+ m_ex = uint.MaxValue;
+ m_ey = uint.MaxValue;
WantsLayer = true;
LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}
@@ -213,20 +217,61 @@ namespace SpriteEd
}
}
+ private NSSpriteEditWindowDelegate Delegate
+ {
+ get
+ {
+ NSSpriteEditWindowDelegate del = null;
+
+ if (Window != null && Window.Delegate != null)
+ {
+ del = Window.Delegate as NSSpriteEditWindowDelegate;
+ }
+
+ return del;
+ }
+ }
+
/// <summary>
/// Save the undo state.
/// </summary>
- private void SaveUndo()
+ private void SaveUndo(string action)
{
- m_undo.CopyFrom(m_sprite);
+ NSSpriteEditWindowDelegate del = Delegate;
+
+ if (del != null)
+ {
+ m_undo.Push(new Sprite(m_sprite));
+ del.UndoManager.SetActionName(action);
+
+ // I think I should be able to put a Sprite instance for the target
+ // but this seems to cause a crash deep in the runtime.
+ //
+ del.UndoManager.RegisterUndo(this, Undo);
+ }
+ }
+
+ private void ClearUndo()
+ {
+ NSSpriteEditWindowDelegate del = Delegate;
+
+ if (del != null)
+ {
+ del.UndoManager.RemoveAllActions();
+ m_undo.Clear();
+ }
}
/// <summary>
/// Undo the last change.
/// </summary>
- public void Undo()
+ /// <param name="ignored">Ignored.</param>
+ public void Undo(NSObject ignored)
{
- m_sprite.CopyFrom(m_undo);
+ Sprite tmp = m_undo.Pop();
+
+ m_sprite.CopyFrom(tmp);
+
NeedsDisplay = true;
}
@@ -649,14 +694,14 @@ namespace SpriteEd
case DrawingMode.Point:
if (m_sprite[m_sx, m_sy] != Colour)
{
- SaveUndo();
+ SaveUndo("draw points");
m_sprite[m_sx, m_sy] = Colour;
NeedsDisplay = true;
}
break;
case DrawingMode.FloodFill:
- SaveUndo();
+ SaveUndo("fill");
FloodFill((int)m_sx, (int)m_sy, m_sprite[m_sx, m_sy]);
NeedsDisplay = true;
break;
@@ -710,37 +755,37 @@ namespace SpriteEd
switch(Mode)
{
case DrawingMode.Line:
- SaveUndo();
+ SaveUndo("line");
DrawSpriteLine(null);
break;
case DrawingMode.Rect:
- SaveUndo();
+ SaveUndo("rectangle");
DrawSpriteRect(null, false);
break;
case DrawingMode.FilledRect:
- SaveUndo();
+ SaveUndo("filled rectangle");
DrawSpriteRect(null, true);
break;
case DrawingMode.Circle:
- SaveUndo();
+ SaveUndo("circle");
DrawSpriteEllipse(null, true, false);
break;
case DrawingMode.FilledCircle:
- SaveUndo();
+ SaveUndo("filled circle");
DrawSpriteEllipse(null, true, true);
break;
case DrawingMode.Ellipse:
- SaveUndo();
+ SaveUndo("ellipse");
DrawSpriteEllipse(null, false, false);
break;
case DrawingMode.FilledEllipse:
- SaveUndo();
+ SaveUndo("filled ellipse");
DrawSpriteEllipse(null, false, true);
break;
diff --git a/SpriteEd/NSSpriteEditWindowDelegate.cs b/SpriteEd/NSSpriteEditWindowDelegate.cs
new file mode 100644
index 0000000..d0cf4e0
--- /dev/null
+++ b/SpriteEd/NSSpriteEditWindowDelegate.cs
@@ -0,0 +1,86 @@
+// SpriteEd - Simple sprite editor
+// Copyright 2020 Ian Cowburn
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+using System;
+using AppKit;
+using Foundation;
+
+namespace SpriteEd
+{
+ public class NSSpriteEditWindowDelegate : NSWindowDelegate
+ {
+ private NSUndoManager m_manager;
+
+ /// <summary>
+ /// Default constructor.
+ /// </summary>
+ public NSSpriteEditWindowDelegate() : base()
+ {
+ Init();
+ }
+
+ /// <summary>
+ /// Construct given handle.
+ /// </summary>
+ /// <param name="handle">The handle.</param>
+ public NSSpriteEditWindowDelegate(IntPtr handle) : base(handle)
+ {
+ Init();
+ }
+
+ /// <summary>
+ /// Initialise the delegate.
+ /// </summary>
+ private void Init()
+ {
+ m_manager = new NSUndoManager();
+ }
+
+ /// <summary>
+ /// Get the Undo Manager.
+ /// </summary>
+ public NSUndoManager UndoManager
+ {
+ get
+ {
+ return m_manager;
+ }
+ }
+
+ /// <summary>
+ /// Override windowWillReturnUndoManager.
+ /// </summary>
+ /// <param name="window">The window.</param>
+ /// <returns>The Undo Manager.</returns>
+ [Export("windowWillReturnUndoManager:")]
+ public override NSUndoManager WillReturnUndoManager(NSWindow window)
+ {
+ return UndoManager;
+ }
+
+ /// <summary>
+ /// Get the current ViewController.
+ /// </summary>
+ private ViewController ViewController
+ {
+ get
+ {
+ NSWindowController controller = NSApplication.SharedApplication.KeyWindow.WindowController as NSWindowController;
+ return controller.ContentViewController as ViewController;
+ }
+ }
+ }
+}
diff --git a/SpriteEd/Sprite.cs b/SpriteEd/Sprite.cs
index c3da98a..024820c 100644
--- a/SpriteEd/Sprite.cs
+++ b/SpriteEd/Sprite.cs
@@ -16,13 +16,14 @@
//
using System;
using System.IO;
+using Foundation;
namespace SpriteEd
{
/// <summary>
/// Represents a sprite.
/// </summary>
- public class Sprite
+ public class Sprite : NSObject
{
private uint[,] m_data;
@@ -49,6 +50,15 @@ namespace SpriteEd
}
/// <summary>
+ /// Create a sprite from the passed sprite.
+ /// </summary>
+ /// <param name="other">The sprite to copy.</param>
+ public Sprite(Sprite other)
+ {
+ CopyFrom(other);
+ }
+
+ /// <summary>
/// Set/get a pixel value in the sprite.
/// </summary>
/// <param name="x">The X co-ord of the pixel.</param>
diff --git a/SpriteEd/SpriteEd.csproj b/SpriteEd/SpriteEd.csproj
index 1fa7dc2..b8b98bd 100644
--- a/SpriteEd/SpriteEd.csproj
+++ b/SpriteEd/SpriteEd.csproj
@@ -88,6 +88,7 @@
<Compile Include="CodePoints.cs" />
<Compile Include="SpriteSetController.cs" />
<Compile Include="SpriteSetController.designer.cs" />
+ <Compile Include="NSSpriteEditWindowDelegate.cs" />
</ItemGroup>
<ItemGroup>
<InterfaceDefinition Include="Main.storyboard" />
diff --git a/SpriteEd/ViewController.cs b/SpriteEd/ViewController.cs
index 12a503f..43fdc64 100644
--- a/SpriteEd/ViewController.cs
+++ b/SpriteEd/ViewController.cs
@@ -24,6 +24,7 @@ namespace SpriteEd
{
private SpriteSet m_SpriteSet;
private NSUrl m_Url;
+ private static int m_Untitled = 1;
public ViewController(IntPtr handle) : base(handle)
{
@@ -37,12 +38,31 @@ namespace SpriteEd
palette[0] = new Colour(0, 0, 0);
palette[1] = new Colour(255, 255, 255);
- Title = "Untitled";
Untitled = true;
SpriteSet = new SpriteSet(SpriteSet.SetType.C64CharacterSet, 8, 8, palette, false, false, CodePoints.C64);
}
+ public override void ViewDidAppear()
+ {
+ base.ViewDidAppear();
+
+ View.Window.Delegate = new NSSpriteEditWindowDelegate();
+
+ if (Untitled)
+ {
+ if (m_Untitled == 1)
+ {
+ View.Window.Title = "Untitled";
+ m_Untitled++;
+ }
+ else
+ {
+ View.Window.Title = String.Format("Untitled {0}", m_Untitled++);
+ }
+ }
+ }
+
public override NSObject RepresentedObject
{
get