using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
namespace SCJMapper_V2
{
///
/// Maintains the complete ActionMaps - something like:
///
///
///
///
///
///
/// ...
///
///
///
class ActionMapsCls : List
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
#region Static Part of ActionMaps
// actionmap names to gather (do we need them to be cofigurable ??)
public static String[] ActionMaps = { };
public static void LoadActionMaps( )
{
// load actionmaps
String acm = AppConfiguration.AppConfig.scActionmaps;
ActionMaps = acm.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries );
}
#endregion Static Part of ActionMaps
private String version { get; set; }
private String ignoreversion { get; set; }
private JoystickList m_joystickList = null;
private UICustHeader m_uiCustHeader = null;
private Options m_options = null;
private Deviceoptions m_deviceOptions = null;
// own additions for JS mapping - should not harm..
private String[] m_js;
private String[] m_GUIDs;
///
/// get/set jsN assignment (use 0-based index i.e. js1 -> [0])
///
public String[] jsN
{
get { return m_js; }
}
///
/// get/set jsN GUID assignment (use 0-based index i.e. js1GUID -> [0])
///
public String[] jsNGUID
{
get { return m_GUIDs; }
}
// provide access to Tuning items of the Options obj to the owner
///
/// Returns the X-Tuning item
///
public JoystickTuningParameter TuningX
{
get { return m_options.TuneX; }
}
///
/// Returns the Y-Tuning item
///
public JoystickTuningParameter TuningY
{
get { return m_options.TuneY; }
}
///
/// Returns the Z-Tuning item
///
public JoystickTuningParameter TuningZ
{
get { return m_options.TuneZ; }
}
///
/// ctor
///
public ActionMapsCls( JoystickList jsList )
{
version = "0";
m_joystickList = jsList; // have to save this for Reassign
// create the Joystick assignments
Array.Resize( ref m_js, JoystickCls.JSnum_MAX + 1 );
Array.Resize( ref m_GUIDs, JoystickCls.JSnum_MAX + 1 );
for ( int i=0; i < JoystickCls.JSnum_MAX; i++ ) {
m_js[i] = ""; m_GUIDs[i] = "";
}
// create options objs
m_uiCustHeader = new UICustHeader( );
m_options = new Options( m_joystickList );
m_deviceOptions = new Deviceoptions( m_options );
LoadActionMaps( ); // get them from config
}
///
/// Copy return all ActionMaps while reassigning the JsN Tag
///
/// The JsN reassign list
/// The ActionMaps copy with reassigned input
public ActionMapsCls ReassignJsN( Dictionary newJsList )
{
ActionMapsCls newMaps = new ActionMapsCls( m_joystickList );
// full copy from 'this'
newMaps.m_uiCustHeader = this.m_uiCustHeader;
newMaps.m_deviceOptions = this.m_deviceOptions;
newMaps.m_options = this.m_options;
for ( int i=0; i < JoystickCls.JSnum_MAX; i++ ) {
newMaps.jsN[i] = this.jsN[i]; newMaps.jsNGUID[i] = this.jsNGUID[i];
}
foreach ( ActionMapCls am in this ) {
newMaps.Add( am.ReassignJsN( newJsList ) );
}
m_options.ReassignJsN( newJsList );
return newMaps;
}
///
/// Merge the given Map with this Map
/// new ones are ignored - we don't learn from XML input for the time beeing
///
///
private void Merge( ActionMapCls newAcm )
{
log.Debug( "Merge - Entry" );
// do we find an actionmap like the new one in our list ?
ActionMapCls ACM = this.Find( delegate( ActionMapCls acm ) {
return acm.name == newAcm.name;
} );
if ( ACM == null ) {
; // this.Add( newAcm ); // no, add new
}
else {
ACM.Merge( newAcm ); // yes, merge it
}
}
///
/// Dump the ActionMaps as partial XML nicely formatted
///
/// the action as XML fragment
public String toXML( )
{
log.Debug( "toXML - Entry" );
AppSettings appSettings = new AppSettings( );
// handle the versioning of the actionmaps
String r = "\n" );
// and dump the option contents
if ( m_uiCustHeader.Count > 0 ) r += m_uiCustHeader.toXML( ) + String.Format( "\n" );
if ( m_options.Count > 0 ) r += m_options.toXML( ) + String.Format( "\n" );
if ( m_deviceOptions.Count > 0 ) r += m_deviceOptions.toXML( ) + String.Format( "\n" );
// finally the action maps
foreach ( ActionMapCls amc in this ) {
r += String.Format( "{0}\n", amc.toXML( ) );
}
r += String.Format( "\n" );
return r;
}
///
/// Read an ActionMaps from XML - do some sanity check
///
/// the XML action fragment
/// True if an action was decoded
public Boolean fromXML( String xml )
{
log.Debug( "fromXML - Entry" );
// Reset those options...
m_uiCustHeader = new UICustHeader( );
m_options = new Options( m_joystickList );
m_deviceOptions = new Deviceoptions( m_options );
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
if ( reader.Name == "ActionMaps" ) {
if ( reader.HasAttributes ) {
version = reader["version"];
ignoreversion = reader["ignoreVersion"]; // could be either / or ..
// get the joystick mapping if there is one
for ( int i=0; i < JoystickCls.JSnum_MAX; i++ ) {
jsN[i] = reader[String.Format( "js{0}", i + 1 )];
jsNGUID[i] = reader[String.Format( "js{0}G", i + 1 )];
}
}
else {
return false;
}
}
reader.Read( ); // move to next element
// could be actionmap OR (AC 0.9) deviceoptions OR options
while ( !reader.EOF ) { //!String.IsNullOrEmpty( x ) ) {
if ( reader.Name == "actionmap" ) {
String x = reader.ReadOuterXml( );
ActionMapCls acm = new ActionMapCls( );
if ( acm.fromXML( x ) ) {
this.Merge( acm ); // merge list
}
}
else if ( reader.Name == "CustomisationUIHeader" ) {
String x = reader.ReadOuterXml( );
m_uiCustHeader.fromXML( x );
}
else if ( reader.Name == "deviceoptions" ) {
String x = reader.ReadOuterXml( );
m_deviceOptions.fromXML( x );
}
else if ( reader.Name == "options" ) {
String x = reader.ReadOuterXml( );
m_options.fromXML( x );
}
else {
reader.Read( );
}
}
return true;
}
}
}