429 lines
12 KiB
C#
429 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using UniversalEditor.Accessors;
|
|
using UniversalEditor.ObjectModels.PropertyList;
|
|
using UniversalEditor.DataFormats.PropertyList.XML;
|
|
|
|
namespace UniversalEditor.UserInterface.WindowsForms
|
|
{
|
|
public partial class Editor : UserControl, IEditorImplementation
|
|
{
|
|
private bool mvarInhibitUndo = false;
|
|
protected bool InhibitUndo { get { return mvarInhibitUndo; } set { mvarInhibitUndo = value; } }
|
|
|
|
private Toolbox mvarToolbox = new Toolbox();
|
|
protected Toolbox Toolbox { get { return mvarToolbox; } }
|
|
|
|
private AwesomeControls.PropertyGrid.PropertyGroup.PropertyGroupCollection mvarPropertyGroups = new AwesomeControls.PropertyGrid.PropertyGroup.PropertyGroupCollection(null);
|
|
public AwesomeControls.PropertyGrid.PropertyGroup.PropertyGroupCollection PropertyGroups { get { return mvarPropertyGroups; } }
|
|
|
|
/// <summary>
|
|
/// The event raised when a toolbox item is selected. Use this to change the current Editor's internal mode without
|
|
/// actually affecting the content of the ObjectModel.
|
|
/// </summary>
|
|
public event ToolboxItemEventHandler ToolboxItemSelected;
|
|
protected virtual void OnToolboxItemSelected(ToolboxItemEventArgs e)
|
|
{
|
|
if (ToolboxItemSelected != null) ToolboxItemSelected(this, e);
|
|
}
|
|
/// <summary>
|
|
/// The event raised when a toolbox item is added to the Editor. Use this to adjust the content of the ObjectModel
|
|
/// based on which toolbox item was added.
|
|
/// </summary>
|
|
public event ToolboxItemEventHandler ToolboxItemAdded;
|
|
protected virtual void OnToolboxItemAdded(ToolboxItemEventArgs e)
|
|
{
|
|
if (ToolboxItemAdded != null) ToolboxItemAdded(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Causes the editor to select the specified toolbox item.
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <returns>True if the editor accepted the new selection; false otherwise. Update the toolbox user interface accordingly.</returns>
|
|
public bool SelectToolboxItem(ToolboxItem item)
|
|
{
|
|
ToolboxItemEventArgs e = new ToolboxItemEventArgs(item);
|
|
OnToolboxItemSelected(e);
|
|
if (e.Cancel) return false;
|
|
return true;
|
|
}
|
|
|
|
protected override void OnDragEnter(DragEventArgs e)
|
|
{
|
|
base.OnDragEnter(e);
|
|
if (e.Data.GetDataPresent(typeof(ToolboxItem)))
|
|
{
|
|
e.Effect = DragDropEffects.Copy;
|
|
}
|
|
}
|
|
protected override void OnDragDrop(DragEventArgs e)
|
|
{
|
|
base.OnDragDrop(e);
|
|
if (e.Data.GetDataPresent(typeof(ToolboxItem)))
|
|
{
|
|
ToolboxItem item = (e.Data.GetData(typeof(ToolboxItem)) as ToolboxItem);
|
|
ToolboxItemEventArgs e1 = new ToolboxItemEventArgs(item);
|
|
OnToolboxItemAdded(e1);
|
|
}
|
|
}
|
|
|
|
public event CancelEventHandler DocumentClosing;
|
|
protected virtual void OnDocumentClosing(CancelEventArgs e)
|
|
{
|
|
if (DocumentClosing != null) DocumentClosing(this, e);
|
|
}
|
|
public event EventHandler DocumentClosed;
|
|
protected virtual void OnDocumentClosed(EventArgs e)
|
|
{
|
|
if (DocumentClosed != null) DocumentClosed(this, e);
|
|
}
|
|
|
|
private UniversalEditor.ObjectModels.PropertyList.PropertyListObjectModel mvarConfiguration = new UniversalEditor.ObjectModels.PropertyList.PropertyListObjectModel();
|
|
public UniversalEditor.ObjectModels.PropertyList.PropertyListObjectModel Configuration { get { return mvarConfiguration; } }
|
|
|
|
public Editor()
|
|
{
|
|
InitializeComponent();
|
|
|
|
mvarLargeImageList.ColorDepth = ColorDepth.Depth32Bit;
|
|
mvarLargeImageList.ImageSize = new System.Drawing.Size(32, 32);
|
|
IconMethods.PopulateSystemIcons(ref mvarLargeImageList);
|
|
|
|
string largeImageListPath = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
|
|
{
|
|
DataPath,
|
|
"Images",
|
|
"ImageList",
|
|
"32x32"
|
|
});
|
|
if (System.IO.Directory.Exists(largeImageListPath))
|
|
{
|
|
string[] fileNames = System.IO.Directory.GetFiles(largeImageListPath);
|
|
foreach (string fileName in fileNames)
|
|
{
|
|
try
|
|
{
|
|
Image image = Image.FromFile(fileName);
|
|
mvarLargeImageList.Images.Add(System.IO.Path.GetFileNameWithoutExtension(fileName), image);
|
|
}
|
|
catch (System.OutOfMemoryException)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
mvarSmallImageList.ColorDepth = ColorDepth.Depth32Bit;
|
|
mvarSmallImageList.ImageSize = new System.Drawing.Size(16, 16);
|
|
IconMethods.PopulateSystemIcons(ref mvarSmallImageList);
|
|
|
|
string smallImageListPath = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
|
|
{
|
|
DataPath,
|
|
"Images",
|
|
"ImageList",
|
|
"16x16"
|
|
});
|
|
if (System.IO.Directory.Exists(smallImageListPath))
|
|
{
|
|
string[] fileNames = System.IO.Directory.GetFiles(smallImageListPath);
|
|
foreach (string fileName in fileNames)
|
|
{
|
|
try
|
|
{
|
|
Image image = Image.FromFile(fileName);
|
|
mvarSmallImageList.Images.Add(System.IO.Path.GetFileNameWithoutExtension(fileName), image);
|
|
}
|
|
catch (System.OutOfMemoryException)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
string configurationPath = String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
|
|
{
|
|
DataPath,
|
|
"Configuration"
|
|
});
|
|
|
|
if (System.IO.Directory.Exists(configurationPath))
|
|
{
|
|
string[] fileNames = System.IO.Directory.GetFiles(configurationPath, "*.xml");
|
|
XMLPropertyListDataFormat xmpl = new XMLPropertyListDataFormat();
|
|
|
|
foreach (string fileName in fileNames)
|
|
{
|
|
try
|
|
{
|
|
PropertyListObjectModel plom = new PropertyListObjectModel();
|
|
Document.Load(plom, xmpl, new FileAccessor(fileName), true);
|
|
plom.CopyTo(mvarConfiguration);
|
|
}
|
|
catch (InvalidDataFormatException ex)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private ImageList mvarLargeImageList = new ImageList();
|
|
protected ImageList LargeImageList { get { return mvarLargeImageList; } }
|
|
|
|
private ImageList mvarSmallImageList = new ImageList();
|
|
protected ImageList SmallImageList { get { return mvarSmallImageList; } }
|
|
|
|
#region IEditorImplementation Members
|
|
public virtual string Title { get { return String.Empty; } }
|
|
|
|
public virtual void Copy()
|
|
{
|
|
}
|
|
public virtual void Paste()
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// Causes the editor to delete the currently-selected item.
|
|
/// </summary>
|
|
public virtual void Delete()
|
|
{
|
|
}
|
|
|
|
private ObjectModelReference.ObjectModelReferenceCollection mvarSupportedObjectModels = new ObjectModelReference.ObjectModelReferenceCollection();
|
|
public ObjectModelReference.ObjectModelReferenceCollection SupportedObjectModels { get { return mvarSupportedObjectModels; } }
|
|
|
|
private ObjectModel mvarObjectModel = null;
|
|
public ObjectModel ObjectModel
|
|
{
|
|
get { return mvarObjectModel; }
|
|
set
|
|
{
|
|
ObjectModelChangingEventArgs omce = new ObjectModelChangingEventArgs(mvarObjectModel, value);
|
|
OnObjectModelChanging(omce);
|
|
if (omce.Cancel) return;
|
|
|
|
mvarObjectModel = omce.NewObjectModel;
|
|
OnObjectModelChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
#endregion
|
|
#region Implementation
|
|
|
|
public event ObjectModelChangingEventHandler ObjectModelChanging;
|
|
protected virtual void OnObjectModelChanging(ObjectModelChangingEventArgs e)
|
|
{
|
|
if (ObjectModelChanging != null) ObjectModelChanging(this, e);
|
|
}
|
|
public event EventHandler ObjectModelChanged;
|
|
protected virtual void OnObjectModelChanged(EventArgs e)
|
|
{
|
|
if (ObjectModelChanged != null) ObjectModelChanged(this, e);
|
|
}
|
|
|
|
public event CancelEventHandler ObjectModelSaving;
|
|
protected virtual void OnObjectModelSaving(CancelEventArgs e)
|
|
{
|
|
if (ObjectModelSaving != null) ObjectModelSaving(this, e);
|
|
}
|
|
|
|
private struct EDITINFO
|
|
{
|
|
public object item;
|
|
public string propertyName;
|
|
public object oldValue;
|
|
public bool closed;
|
|
|
|
public EDITINFO(object item, string propertyName, object oldValue)
|
|
{
|
|
this.item = item;
|
|
this.propertyName = propertyName;
|
|
this.oldValue = oldValue;
|
|
this.closed = false;
|
|
}
|
|
}
|
|
|
|
private Stack<EDITINFO> undo = new Stack<EDITINFO>();
|
|
public int UndoItemCount { get { return undo.Count; } }
|
|
private Stack<EDITINFO> redo = new Stack<EDITINFO>();
|
|
public int RedoItemCount { get { return redo.Count; } }
|
|
|
|
public event EventHandler DocumentEdited;
|
|
protected virtual void OnDocumentEdited(EventArgs e)
|
|
{
|
|
if (DocumentEdited != null) DocumentEdited(this, e);
|
|
}
|
|
|
|
private int mvarEditing = 0;
|
|
|
|
protected void BeginEdit()
|
|
{
|
|
if (mvarEditing > 0)
|
|
{
|
|
mvarEditing++;
|
|
return;
|
|
}
|
|
mvarEditing++;
|
|
|
|
// check to see if this property has been edited before
|
|
if (undo.Count > 0)
|
|
{
|
|
EDITINFO oldedit = undo.Pop();
|
|
if (oldedit.closed) undo.Push(oldedit);
|
|
}
|
|
|
|
// push the new edit
|
|
EDITINFO edit = new EDITINFO(null, null, mvarObjectModel);
|
|
undo.Push(edit);
|
|
|
|
// clear out all the redos
|
|
redo.Clear();
|
|
}
|
|
protected void BeginEdit(string PropertyName, object Value = null, object ParentObject = null)
|
|
{
|
|
if (mvarEditing > 0)
|
|
{
|
|
mvarEditing++;
|
|
return;
|
|
}
|
|
mvarEditing++;
|
|
|
|
if (ParentObject == null) ParentObject = ObjectModel;
|
|
|
|
// check to see if this property has been edited before
|
|
if (undo.Count > 0)
|
|
{
|
|
EDITINFO oldedit = undo.Pop();
|
|
if (oldedit.propertyName != PropertyName || oldedit.closed) undo.Push(oldedit);
|
|
}
|
|
|
|
// push the new edit
|
|
if (Value == null)
|
|
{
|
|
System.Reflection.PropertyInfo pi = ParentObject.GetType().GetProperty(PropertyName);
|
|
if (pi != null)
|
|
{
|
|
Value = ParentObject.GetType().GetProperty(PropertyName).GetValue(ParentObject, null);
|
|
}
|
|
}
|
|
|
|
EDITINFO edit = new EDITINFO(ParentObject, PropertyName, Value);
|
|
undo.Push(edit);
|
|
|
|
// clear out all the redos
|
|
redo.Clear();
|
|
}
|
|
protected void EndEdit()
|
|
{
|
|
if (mvarEditing == 0) return; // throw new InvalidOperationException();
|
|
if (mvarEditing > 1)
|
|
{
|
|
mvarEditing--;
|
|
return;
|
|
}
|
|
|
|
if (undo.Count == 0) return;
|
|
EDITINFO oldedit = undo.Pop();
|
|
oldedit.closed = true;
|
|
undo.Push(oldedit);
|
|
|
|
// notify the object model that it's being edited
|
|
OnDocumentEdited(EventArgs.Empty);
|
|
|
|
mvarEditing--;
|
|
}
|
|
|
|
public virtual void Undo()
|
|
{
|
|
if (undo.Count == 0) return;
|
|
|
|
EDITINFO edi = undo.Pop();
|
|
EDITINFO newedi = edi;
|
|
|
|
if (edi.propertyName != null)
|
|
{
|
|
// get the property that owns this edit
|
|
System.Reflection.PropertyInfo pi = edi.item.GetType().GetProperty(edi.propertyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
|
|
|
// get the current value of the property, for a "redo"
|
|
object newValue = pi.GetValue(edi.item, null);
|
|
newedi = new EDITINFO(edi.item, edi.propertyName, newValue);
|
|
|
|
// set the current value to the "un-done" value
|
|
pi.SetValue(edi.item, edi.oldValue, null);
|
|
}
|
|
else
|
|
{
|
|
newedi = new EDITINFO(null, null, mvarObjectModel);
|
|
mvarObjectModel = (edi.oldValue as ObjectModel);
|
|
}
|
|
|
|
// cause a refresh of the editor
|
|
OnObjectModelChanged(EventArgs.Empty);
|
|
|
|
// push the previous value into the redo log
|
|
redo.Push(newedi);
|
|
}
|
|
public virtual void Redo()
|
|
{
|
|
// this is EXACTLY like undo, only in reverse ;)
|
|
if (redo.Count == 0) return;
|
|
|
|
EDITINFO edi = redo.Pop();
|
|
EDITINFO newedi = edi;
|
|
|
|
if (edi.propertyName != null)
|
|
{
|
|
// get the property that owns this edit
|
|
System.Reflection.PropertyInfo pi = edi.item.GetType().GetProperty(edi.propertyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
|
|
|
// get the current value of the property, for a "redo"
|
|
object newValue = pi.GetValue(edi.item, null);
|
|
newedi = new EDITINFO(edi.item, edi.propertyName, newValue);
|
|
|
|
// set the current value to the "un-done" value
|
|
pi.SetValue(edi.item, edi.oldValue, null);
|
|
}
|
|
else
|
|
{
|
|
newedi = new EDITINFO(null, null, mvarObjectModel);
|
|
mvarObjectModel = (edi.oldValue as ObjectModel);
|
|
}
|
|
|
|
// cause a refresh of the editor
|
|
OnObjectModelChanged(EventArgs.Empty);
|
|
|
|
// push the previous value into the undo log
|
|
undo.Push(newedi);
|
|
}
|
|
#endregion
|
|
|
|
private MenuBar mvarMenuBar = new MenuBar();
|
|
public MenuBar MenuBar { get { return mvarMenuBar; } }
|
|
|
|
private Toolbar.ToolbarCollection mvarToolbars = new Toolbar.ToolbarCollection();
|
|
public Toolbar.ToolbarCollection Toolbars { get { return mvarToolbars; } }
|
|
|
|
public bool NotifySaving()
|
|
{
|
|
CancelEventArgs ce = new CancelEventArgs();
|
|
OnObjectModelSaving(ce);
|
|
if (ce.Cancel) return false;
|
|
return true;
|
|
}
|
|
|
|
public void NotifyClosing(CancelEventArgs ce)
|
|
{
|
|
OnDocumentClosing(ce);
|
|
}
|
|
public void NotifyClosed(EventArgs e)
|
|
{
|
|
OnDocumentClosed(e);
|
|
}
|
|
|
|
public string DataPath { get { return String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] { "Editors", this.GetType().FullName }); } }
|
|
}
|
|
}
|