//-----------------------------------------------------------------------------
// CurveEditor.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
namespace Xna.Tools
{
public partial class CurveEditor : Form
{
public CurveEditor()
{
InitializeComponent();
if (Site != null) Site.Container.Add(curveControl);
}
#region Internal Methods
internal void UpdateCurveItems(IList newItems, IList selection)
{
disableUIEvents++;
curveListView.BeginUpdate();
ArrayList oldItems = new ArrayList(curveListView.Items);
curveListView.Items.Clear();
// Add new items.
foreach (ListViewItem item in newItems)
{
curveListView.Items.Add(item);
if (!oldItems.Contains(item))
curveControl.Curves.Add(CurveFileInfo.GetCurve(item));
}
// Remove items from Curve control that not exist new items.
foreach (ListViewItem item in oldItems)
{
if (!curveListView.Items.Contains(item))
curveControl.Curves.Remove(CurveFileInfo.GetCurve(item));
}
ApplySelection(selection);
curveListView.EndUpdate();
disableUIEvents--;
}
internal void ApplySelection(IList selection)
{
disableUIEvents++;
curveListView.BeginUpdate();
// Update selection
curveListView.SelectedItems.Clear();
foreach (ListViewItem item in selection)
item.Selected = true;
curveListView.EndUpdate();
disableUIEvents--;
}
#endregion
protected override void OnFormClosing(FormClosingEventArgs e)
{
foreach ( ListViewItem item in curveListView.Items )
{
EditCurve curve = CurveFileInfo.GetCurve(item);
if ( curve.Dirty )
{
DialogResult dr = MessageBox.Show(
String.Format( CurveEditorResources.SaveMessage, curve.Name ),
CurveEditorResources.CurveEditorTitle,
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);
if ( dr == DialogResult.Yes)
dr = SaveCurve(item, false);
if (dr == DialogResult.Cancel)
{
e.Cancel = true;
break;
}
}
}
base.OnFormClosing(e);
}
#region Event handle methods
private void curveListView_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
if (disableUIEvents > 0) return;
// Label edit has been canceled.
if (String.IsNullOrEmpty(e.Label)) return;
//
commandHistory.BeginRecordCommands();
curveControl.BeginUpdate();
string newName = EnsureUniqueName(e.Label);
e.CancelEdit = String.Compare(newName, e.Label) != 0;
curveListView.Items[e.Item].Text = newName;
EditCurve curve = CurveFileInfo.GetCurve(curveListView.Items[e.Item]);
curve.Name = newName;
curveControl.EndUpdate();
commandHistory.EndRecordCommands();
}
private void CurveEditor_Load(object sender, EventArgs e)
{
commandHistory = CommandHistory.EnsureHasService(Site);
}
private void curveListView_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
RemoveSelectedCurves();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateCurve();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
foreach (string filename in openFileDialog1.FileNames)
{
string name =
EnsureUniqueName(Path.GetFileNameWithoutExtension(filename));
EditCurve editCurve = EditCurve.LoadFromFile(filename, name,
NextCurveColor(), commandHistory);
ListViewItem item = CreateCurve(editCurve, name);
CurveFileInfo.AssignFilename(item, filename);
}
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveCurves(false);
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveCurves(true);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
using (HelpAbout about = new HelpAbout())
{
about.ShowDialog();
}
}
private void curveListView_SelectedIndexChanged(object sender, EventArgs e)
{
if (disableUIEvents > 0) return;
UpdateCurveEditables();
curveControl.Invalidate(true);
}
private void curveListView_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (disableUIEvents > 0) return;
CurveFileInfo.GetCurve(e.Item).Visible = e.Item.Checked;
curveControl.Invalidate(true);
}
private void editCurve_StateChanged(object sender, EventArgs e)
{
disableUIEvents++;
curveListView.BeginUpdate();
EditCurve curve = sender as EditCurve;
ListViewItem item = idToItemMap[curve.Id];
item.Text = curve.Name;
disableUIEvents--;
curveListView.EndUpdate();
}
#endregion
#region Private methods
private System.Drawing.Color NextCurveColor()
{
System.Drawing.Color result = curveColors[curveColorIndex++];
if (curveColorIndex >= curveColors.Length) curveColorIndex = 0;
return result;
}
private ListViewItem CreateCurve(EditCurve editCurve, string name)
{
editCurve.Id = GenerateUniqueCurveId();
editCurve.StateChanged += new EventHandler(editCurve_StateChanged);
ListViewItem item = new ListViewItem(name);
item.Checked = true;
CurveFileInfo.AssignCurve(item, editCurve);
idToItemMap.Add(editCurve.Id, item);
ArrayList oldItems = new ArrayList(curveListView.Items);
ArrayList oldSelection = new ArrayList(curveListView.SelectedItems);
ArrayList newItems = new ArrayList(curveListView.Items);
ListViewItem[] newSelection = { item };
newItems.Add(item);
//curveListView.Items.Add(item);
//curveListView.SelectedItems.Clear();
//item.Selected = true;
commandHistory.BeginRecordCommands();
commandHistory.Do( new CurveAddRemoveCommand(this, oldItems, newItems,
oldSelection, newSelection));
UpdateCurveEditables();
commandHistory.EndRecordCommands();
return item;
}
private ListViewItem CreateCurve()
{
string name = EnsureUniqueName("Curve");
Curve curve = new Curve();
curve.Keys.Add(new CurveKey(0, 0));
EditCurve editCurve =
new EditCurve(name, NextCurveColor(), curve, commandHistory);
editCurve.Dirty = true;
return CreateCurve(editCurve, name);
}
private void UpdateCurveEditables()
{
UpdateCurves(delegate(ListViewItem item, EditCurve curve)
{
curve.Editable = item.Selected;
});
}
private void RemoveSelectedCurves()
{
commandHistory.BeginRecordCommands();
ArrayList newItems = new ArrayList();
ArrayList newSelection = new ArrayList();
foreach (ListViewItem item in curveListView.Items)
{
if (!item.Selected)
{
newItems.Add(item);
if (newSelection.Count == 0 )newSelection.Add(item);
}
}
ArrayList oldItems = new ArrayList(curveListView.Items);
ArrayList oldSelection = new ArrayList(curveListView.SelectedItems);
commandHistory.Do( new CurveAddRemoveCommand(this, oldItems, newItems,
oldSelection, newSelection));
UpdateCurveEditables();
commandHistory.EndRecordCommands();
}
private string EnsureUniqueName(string candidateName)
{
string name =
String.IsNullOrEmpty(candidateName) ? "Empty" : candidateName;
int num = 1;
bool found = false;
do
{
found = false;
foreach (ListViewItem item in curveListView.Items)
{
int result = String.Compare(
item.Text, name, true, CultureInfo.InvariantCulture);
if (result == 0)
{
found = true;
name = String.Format("{0}#{1}", candidateName, num++);
break;
}
}
} while (found);
return name;
}
///
/// Update curves.
///
///
private void UpdateCurves(UpdateCurveDelegate callback)
{
curveControl.BeginUpdate();
foreach (ListViewItem item in curveListView.Items)
callback(item, CurveFileInfo.GetCurve(item));
curveControl.EndUpdate();
}
private DialogResult SaveCurve(ListViewItem item, bool saveAs)
{
string filename = CurveFileInfo.GetFilename(item);
if (String.IsNullOrEmpty(filename) || saveAs)
{
saveFileDialog1.Title = saveAs ? "Save Curve As" : "Save Curve";
saveFileDialog1.FileName = Path.ChangeExtension(item.Text, ".xml");
DialogResult dr = saveFileDialog1.ShowDialog();
if (dr == DialogResult.OK)
{
filename = saveFileDialog1.FileName;
CurveFileInfo.AssignFilename(item, filename);
}
if (dr == DialogResult.Cancel) return dr;
}
// Save to file.
if (!String.IsNullOrEmpty(filename))
CurveFileInfo.Save(item, filename);
return DialogResult.OK;
}
private void SaveCurves(bool saveAs)
{
// Save current curves.
foreach (ListViewItem item in curveListView.SelectedItems)
{
if (SaveCurve(item, saveAs) == DialogResult.Cancel) break;
}
}
///
/// Generate Unique Id for EditCurve
/// We need to assign unique Id for each EditCurve for undo/redo.
///
///
private long GenerateUniqueCurveId()
{
return curveId++;
}
delegate void UpdateCurveDelegate(ListViewItem item, EditCurve curve);
#endregion
private long curveId;
private CommandHistory commandHistory;
private Dictionary idToItemMap =
new Dictionary();
private int disableUIEvents;
private System.Drawing.Color[] curveColors = { System.Drawing.Color.Red, System.Drawing.Color.Green, System.Drawing.Color.Blue };
private int curveColorIndex;
class CurveFileInfo
{
public EditCurve Curve;
public string Filename;
public static void AssignCurve( ListViewItem item, EditCurve curve )
{
CurveFileInfo cfi = EnsureFileInfo(item);
cfi.Curve = curve;
}
public static void AssignFilename(ListViewItem item, string filename)
{
CurveFileInfo cfi = EnsureFileInfo(item);
cfi.Filename = filename;
}
public static EditCurve GetCurve(ListViewItem item)
{
return EnsureFileInfo(item).Curve;
}
public static string GetFilename(ListViewItem item)
{
return EnsureFileInfo(item).Filename;
}
public static void Save(ListViewItem item, string filename)
{
GetCurve(item).Save(filename);
}
private static CurveFileInfo EnsureFileInfo(ListViewItem item)
{
if (item.Tag == null)
item.Tag = new CurveFileInfo();
return item.Tag as CurveFileInfo;
}
}
}
}