using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Linq;
namespace SCJMapper_V2.Devices
{
///
/// Maintains an CustomisationUIHeader - something like:
///
///
///
/// or
///
///
///
///
///
///
///
///
public class UICustHeader : ICloneable
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
List m_stringOptions = new List( );
public const string XmlName = "CustomisationUIHeader";
public struct DevRec : ICloneable
{
public string devType;
public int instNo;
public object Clone()
{
var dr = (DevRec)this.MemberwiseClone( );
return dr;
}
///
/// Check clone against This
///
///
/// True if the clone is identical but not a shallow copy
public bool CheckClone( DevRec clone )
{
bool ret = true;
ret &= ( this.devType == clone.devType ); // immutable string - shallow copy is OK
ret &= ( this.instNo == clone.instNo ); // value type
return ret;
}
}
List m_devInstances = new List( );
private string m_label = "";
private string m_description = "";
private string m_image = "";
///
/// Clone this object
///
/// A deep Clone of this object
public object Clone()
{
var uic = (UICustHeader)this.MemberwiseClone( );
// more objects to deep copy
uic.m_devInstances = m_devInstances.Select( x => (DevRec)x.Clone( ) ).ToList( );
#if DEBUG
// check cloned item
System.Diagnostics.Debug.Assert( CheckClone( uic ) );
#endif
return uic;
}
///
/// Check clone against This
///
///
/// True if the clone is identical but not a shallow copy
private bool CheckClone( UICustHeader clone )
{
bool ret = true;
ret &= ( this.m_stringOptions == clone.m_stringOptions ); // immutable string list - shallow copy is OK
ret &= ( this.m_label == clone.m_label ); // immutable string - shallow copy is OK
ret &= ( this.m_description == clone.m_description ); // immutable string - shallow copy is OK
ret &= ( this.m_image == clone.m_image ); // immutable string - shallow copy is OK
ret &= ( this.m_devInstances.Count == clone.m_devInstances.Count );
if ( ret ) {
for ( int i = 0; i < this.m_devInstances.Count; i++ ) {
ret &= ( this.m_devInstances[i].CheckClone( clone.m_devInstances[i] ) );
}
}
return ret;
}
public int Count
{
get { return ( m_stringOptions.Count + m_devInstances.Count ); }
}
public string Label
{
get { return m_label; }
set { m_label = value; }
}
public void ClearInstances()
{
m_devInstances.Clear( );
}
public void AddInstances( DevRec dr )
{
m_devInstances.Add( dr );
}
private string[] FormatXml( string xml )
{
try {
XDocument doc = XDocument.Parse( xml );
return doc.ToString( ).Split( new string[] { string.Format( "\n" ) }, StringSplitOptions.RemoveEmptyEntries );
}
catch ( Exception ) {
return new string[] { xml };
}
}
///
/// Dump the CustomisationUIHeader as partial XML nicely formatted
///
/// the action as XML fragment
public string toXML()
{
/*
*/
string r = "";
r += string.Format( "\t<{0} label=\"{1}\" description=\"{2}\" image=\"{3}\">\n", XmlName, m_label, m_description, m_image );
if ( m_devInstances.Count > 0 ) {
r += string.Format( "\t\t\n" );
foreach ( DevRec dr in m_devInstances ) {
r += string.Format( "\t\t\t<{0} instance=\"{1}\"/>\n", dr.devType, dr.instNo.ToString( ) );
}
r += string.Format( "\t\t\n" );
}
// CIG adds them to export - so can we ...
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\t\n" );
r += string.Format( "\t\n" );
// and dump the plain contents if needed
foreach ( string x in m_stringOptions ) {
if ( !string.IsNullOrWhiteSpace( x ) ) {
foreach ( string line in FormatXml( x ) ) {
r += string.Format( "\t{0}", line );
}
}
}
r += string.Format( "\n" );
return r;
}
///
/// Read an CustomisationUIHeader from XML - do some sanity check
///
/// the XML action fragment
/// True if an action was decoded
private bool Instance_fromXML( XElement devices )
{
/*
*/
foreach ( XElement dev in devices.Nodes( ) ) {
string devType = (string)dev.Name.LocalName;
int instNo = 0;
IEnumerable attr = dev.Attributes( ).Where( _a => _a.Name == "instance" );
if ( attr.Count( ) > 0 ) {
if ( !int.TryParse( attr.ElementAt( 0 ).Value.ToString( ), out instNo ) ) {
instNo = 0;
}
else {
DevRec dr = new DevRec( );
dr.devType = devType;
dr.instNo = instNo;
m_devInstances.Add( dr );
}
}
}
return true;
}
///
/// Read an CustomisationUIHeader from XML - do some sanity check
///
/// the XML action fragment
/// True if an action was decoded
public bool fromXML( XElement cuiHeader )
{
/*
*/
m_label = (string)cuiHeader.Attributes( ).First( a => a.Name == "label" ); // mandadory - else Exception
IEnumerable attr = cuiHeader.Attributes( ).Where( _a => _a.Name == "description" );
if ( attr.Count( ) > 0 )
m_description = attr.ElementAt( 0 ).Value.ToString( );
else
m_description = "@ui_JoystickDefaultDesc";
attr = cuiHeader.Attributes( ).Where( _a => _a.Name == "image" );
if ( attr.Count( ) > 0 )
m_image = attr.ElementAt( 0 ).Value.ToString( );
else
m_image = "JoystickDefault";
// try to disassemble the devices items
IEnumerable elements = from x in cuiHeader.Elements( )
where ( x.Name == "devices" )
select x;
foreach ( XElement devices in elements ) {
Instance_fromXML( devices );
}
return true;
}
}
}