/// <summary> /// Returns the command part from a node text /// i.e. v_pitch - js1_x returns js1_x /// </summary> /// <param name="nodeText">The node text in 'action - command' notation</param> /// <returns>the command part or an empty string</returns> public static String CommandFromNodeText(String nodeText) { String action, cmd; ActionTreeNode.DecompNodeText(nodeText, out action, out cmd); return(cmd); }
/// <summary> /// Update this node from the other node /// applies dynamic props only /// </summary> /// <param name="other">The node to update from</param> public void Update(ActionTreeNode other) { this.BackColor = other.BackColor; this.Command = other.Command; this.Modified = other.Modified; this.Action = other.Action; //????????????????? }
// ctor public ActionTreeNode( ActionTreeNode srcNode ) : base() { if ( srcNode == null ) return; this.Name = srcNode.Name; this.Text = srcNode.Text; this.BackColor = srcNode.BackColor; this.ForeColor = srcNode.ForeColor; this.NodeFont = srcNode.NodeFont; this.ImageKey = srcNode.ImageKey; this.Tag = srcNode.Tag; this.m_action = srcNode.m_action; this.m_actionDevice = srcNode.m_actionDevice; }
// ctor public ActionTreeNode(ActionTreeNode srcNode) : base( ) { if (srcNode == null) { return; } this.Name = srcNode.Name; this.Text = srcNode.Text; this.BackColor = srcNode.BackColor; this.ForeColor = srcNode.ForeColor; this.NodeFont = srcNode.NodeFont; this.ImageKey = srcNode.ImageKey; this.Tag = srcNode.Tag; this.m_action = srcNode.m_action; this.m_actionDevice = srcNode.m_actionDevice; }
// ctor public ActionTreeNode(ActionTreeNode srcNode) : base( ) { if (srcNode == null) { return; } // properties set once for a node this.Name = srcNode.Name; this.Text = srcNode.Text; this.ForeColor = srcNode.ForeColor; this.NodeFont = srcNode.NodeFont; this.ImageKey = srcNode.ImageKey; this.Tag = srcNode.Tag; this.m_action = srcNode.m_action; this.m_actionDevice = srcNode.m_actionDevice; // these are changing while using it this.Update(srcNode); }
// ctor public ActionTreeNode( string text, ActionTreeNode[] children ) : base(text, children) { }
private void UpdateMasterNode( ActionTreeNode node ) { // copy to master node TreeNode[] masterNode = m_MasterTree.Nodes.Find( node.Name, true ); // find the same node in master if ( masterNode.Length == 0 ) throw new IndexOutOfRangeException( "ActionTree ERROR - cannot find synched node in master" ); // OUT OF SYNC // could return more than one if the action is the same in different actionmaps foreach ( ActionTreeNode mtn in masterNode ) { if ( mtn.Parent.Name == node.Parent.Name ) { mtn.Command = node.Command; mtn.BackColor = node.BackColor; } } }
/// <summary> /// Find the master element for the given ActionNode /// </summary> /// <param name="atn">The ActionNode to find</param> /// <returns>The sought node or null</returns> private ActionTreeNode FindMasterAction( ActionTreeNode atn ) { if ( atn.Level != 1 ) return null; // sanity TreeNode[] masterNode = m_MasterTree.Nodes.Find( atn.Name, true ); // find the same node in master if ( masterNode.Length == 0 ) throw new IndexOutOfRangeException( "ActionTree ERROR - cannot find synched node in master" ); // OUT OF SYNC // could return more than one if the action is the same in different actionmaps foreach ( ActionTreeNode mtn in masterNode ) { if ( mtn.Parent.Name == atn.Parent.Name ) { return mtn; } } return null; }
/// <summary> /// Apply the filter to the GUI TreeView /// </summary> private void ApplyFilter( ) { log.Debug( "ApplyFilter - Entry" ); ActionTreeNode topNode = null; // allow to backup the view - will carry the first node items Ctrl.BeginUpdate( ); Ctrl.Nodes.Clear( ); // start over // traverse the master tree and build the GUI tree from it foreach ( ActionTreeNode tn in m_MasterTree.Nodes ) { ActionTreeNode tnMap = new ActionTreeNode( tn ); Ctrl.Nodes.Add( tnMap ); // copy level 0 nodes if ( topNode == null ) topNode = tnMap; // have to search nodes of nodes Boolean allHidden = true; foreach ( ActionTreeNode stn in tn.Nodes ) { if ( ( stn.Tag != null ) && ( ( Boolean )stn.Tag == true ) ) { ; // don't create it i.e hide it - though you cannot hide TreeViewNodes at all... } else { ActionTreeNode tnAction = new ActionTreeNode( stn ); tnMap.Nodes.Add( tnAction ); // copy level 1 nodes foreach ( ActionTreeInputNode istn in stn.Nodes ) { ActionTreeInputNode tnActionInput = new ActionTreeInputNode( istn ); tnAction.Nodes.Add( tnActionInput ); // copy level 2 nodes } allHidden = false; } } // make it tidier.. if ( allHidden ) tnMap.Collapse( ); else tnMap.ExpandAll( ); } if ( topNode != null ) Ctrl.TopNode = topNode; // set view to topnode Ctrl.EndUpdate( ); // enable GUI update }
/// <summary> /// Load Mappings into the ActionList and create the Master TreeView /// </summary> /// <param name="defaultProfileName">The name of the profile to load (w/o extension)</param> /// <param name="applyDefaults">True if default mappings should be carried on</param> public void LoadProfileTree( String defaultProfileName, Boolean applyDefaults ) { log.Debug( "LoadProfileTree - Entry" ); ActionTreeNode tn = null; ActionTreeNode[] cnl = { }; ActionTreeNode cn = null; ActionTreeNode topNode = null; ActionMapCls acm = null; ActionCls ac = null; ActionCommandCls acc = null; ActionMaps = new ActionMapsCls( m_jsList ); m_MasterTree.Nodes.Clear( ); // read the action items into the TreeView DProfileReader dpReader = new DProfileReader( ); // we may read a profile TextReader txReader = null; dpReader.fromXML( SCDefaultProfile.DefaultProfile( defaultProfileName + ".xml" ) ); if ( dpReader.ValidContent ) { txReader = new StringReader( dpReader.CSVMap ); } // we assume no addbind items in the profile // so all actions are shown in the ActionTreeNode and no ActionTreeNode childs must be created here // however we create the ActionCommand for each entry that is supported - even if it is not mapped (input= "") using ( TextReader sr = txReader ) { String buf = sr.ReadLine( ); while ( !String.IsNullOrEmpty( buf ) ) { String[] elem = buf.Split( new char[] { ';', ',' } ); if ( elem.Length > 1 ) { if ( !IgnoreMaps.Contains( "," + elem[0] + "," ) ) { // must have 2 elements min Array.Resize( ref cnl, 0 ); acm = new ActionMapCls( ); acm.name = elem[0]; // get actionmap name // process items for ( int ei=1; ei < elem.Length; ei += 2 ) { // step 2 - action;defaultBinding come in pairs if ( !String.IsNullOrEmpty( elem[ei] ) ) { // default assignments String action = elem[ei].Substring( 1 ); String defBinding = elem[ei + 1].Substring( 0 ); String devID = elem[ei].Substring( 0, 1 ); String device = ActionCls.DeviceFromID( devID ); // visual item for the action cn = new ActionTreeNode( "UNDEF" ); cn.Name = elem[ei]; cn.Action = action; cn.BackColor = Color.White; // name with the key it to find it.. cn.ImageKey = devID; cn.BackColor = Color.White; // some stuff does not work properly... Array.Resize( ref cnl, cnl.Length + 1 ); cnl[cnl.Length - 1] = cn; // derive content tree ac = new ActionCls( ); ac.key = cn.Name; ac.name = action; ac.device = device; ac.actionDevice = ActionCls.ADevice( device ); ac.defBinding = defBinding; acm.Add( ac ); // add to our map cn.ActionDevice = ac.actionDevice; // should be known now // create just an unmapped ActionCommand item acc = new ActionCommandCls( ); acc.input = ""; acc.nodeIndex = -1; // profile items are shown in the ActionTreeNode (not in a child) ac.inputList.Add( acc );// add to our Action // modify defaults and blendings if ( applyDefaults ) { // apply the default mappings if ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) { int jNum = JoystickCls.JSNum( ac.defBinding ); if ( JoystickCls.IsJSValid( jNum ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = JoystickCls.JsNColor( jNum ); } else if ( BlendUnmappedJS ) { // jsx_reserved gets here acc.input = JoystickCls.BlendedInput; cn.Command = JoystickCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; } } else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) { if ( GamepadCls.IsXiValid( ac.defBinding ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = GamepadCls.XiColor( ); } else if ( BlendUnmappedGP ) { // xi_reserved gets here acc.input = GamepadCls.BlendedInput; cn.Command = GamepadCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; } } else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Keyboard ) { if ( !String.IsNullOrEmpty( ac.defBinding ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = KeyboardCls.KbdColor( ); } } } // Don't apply defaults - but blend if checked else { if ( ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) && BlendUnmappedJS ) { cn.Command = JoystickCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; acc.input = JoystickCls.BlendedInput; } else if ( ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) && BlendUnmappedGP ) { cn.Command = GamepadCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; acc.input = GamepadCls.BlendedInput; } } } }//for tn = new ActionTreeNode( acm.name, cnl ); tn.Name = acm.name; // name it to find it.. tn.ImageIndex = 0; tn.NodeFont = new Font( m_MasterTree.Font, FontStyle.Bold ); m_MasterTree.BackColor = Color.White; // fix for defect TreeView (cut off bold text) m_MasterTree.Nodes.Add( tn ); // add to control if ( topNode == null ) topNode = tn; // once to keep the start of list ActionMaps.Add( acm ); // add to our map }//not ignored }// if valid line buf = sr.ReadLine( ); }//while } // fix for defect TreeView (cut off bold text at last element -despite the BackColor fix) add another and delete it tn = new ActionTreeNode( "DUMMY" ); tn.Name = "DUMMY"; tn.ImageIndex = 0; tn.NodeFont = new Font( m_MasterTree.Font, FontStyle.Bold ); m_MasterTree.BackColor = m_MasterTree.BackColor; // fix for defect TreeView (cut off bold text) m_MasterTree.Nodes.Add( tn ); // add to control m_MasterTree.Nodes.RemoveByKey( "DUMMY" ); // fix for defect TreeView (cut off bold text) txReader = null; Dirty = false; // finally apply the filter and make it visible FilterTree( ); }
/// <summary> /// Apply an update from the action to the treenode /// First apply to the GUI tree where the selection happend then copy it over to master tree /// </summary> /// <param name="input">The input command</param> /// <param name="node">The TreeNode to update</param> /// <param name="action">The action that carries the update</param> /// <param name="inKind">The input device</param> private void UpdateNodeFromAction( ActionTreeNode node, ActionCommandCls actionCmd, ActionCls.ActionDevice inKind ) { //log.Debug( "UpdateNodeFromAction - Entry" ); if ( actionCmd == null ) return; // applies only to ActionTreeNode if ( node.Level == 1 ) { // input is either "" or a valid mapping or a blended mapping if ( String.IsNullOrEmpty( actionCmd.input ) ) { // new unmapped node.Command = ""; node.BackColor = MyColors.UnassignedColor; } // blended mapped ones - can only get a Blend Background else if ( ( inKind == ActionCls.ActionDevice.AD_Joystick ) && ( actionCmd.input == JoystickCls.BlendedInput ) ) { node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else if ( ( inKind == ActionCls.ActionDevice.AD_Gamepad ) && ( actionCmd.input == GamepadCls.BlendedInput ) ) { node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else if ( actionCmd.input == DeviceCls.BlendedInput ) { // Manually Blended input node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else { // mapped ( regular ones ) node.Command = actionCmd.input; // background is along the input if ( inKind == ActionCls.ActionDevice.AD_Joystick ) { int jNum = JoystickCls.JSNum( actionCmd.input ); node.BackColor = JoystickCls.JsNColor( jNum ); } else if ( inKind == ActionCls.ActionDevice.AD_Gamepad ) { node.BackColor = GamepadCls.XiColor( ); } else if ( inKind == ActionCls.ActionDevice.AD_Keyboard ) { node.BackColor = KeyboardCls.KbdColor( ); } else { // ?? what else node.BackColor = MyColors.UnassignedColor; } } UpdateMasterNode( node ); } }
/// <summary> /// Derive values from a command (e.g. v_pitch - js1_x) /// </summary> private void DecomposeCommand( ) { // populate from input // something like "v_pitch - js1_x" OR "v_pitch - xi_thumbl" OR "v_pitch - ximod+xi_thumbl+xi_mod" String cmd = ActionTree.CommandFromNodeText(Action); String action = ActionTreeNode.ActionFromNodeText(Action); m_cmdCtrl = ""; if (!String.IsNullOrWhiteSpace(cmd)) { // decomp gamepad entries - could have modifiers so check for contains... if (cmd.Contains("xi_thumblx")) { // gamepad m_cmdCtrl = "xi_thumblx"; m_deviceName = m_device.DevName; if (action.Contains("pitch")) { m_option = String.Format("flight_move_pitch"); } else { m_option = String.Format("flight_move_yaw"); } } else if (cmd.Contains("xi_thumbly")) { // gamepad m_cmdCtrl = "xi_thumbly"; m_deviceName = m_device.DevName; if (action.Contains("pitch")) { m_option = String.Format("flight_move_pitch"); } else { m_option = String.Format("flight_move_yaw"); } } else if (cmd.Contains("xi_thumbrx")) { // gamepad m_cmdCtrl = "xi_thumbrx"; m_deviceName = m_device.DevName; if (action.Contains("pitch")) { m_option = String.Format("flight_move_pitch"); } else { m_option = String.Format("flight_move_yaw"); } } else if (cmd.Contains("xi_thumbry")) { // gamepad m_cmdCtrl = "xi_thumbry"; m_deviceName = m_device.DevName; if (action.Contains("pitch")) { m_option = String.Format("flight_move_pitch"); } else { m_option = String.Format("flight_move_yaw"); } } // assume joystick else { // get parts m_cmdCtrl = JoystickCls.ActionFromJsCommand(cmd); //js1_x -> x; js2_rotz -> rotz m_deviceName = m_device.DevName; if (action.Contains("pitch")) { m_option = String.Format("flight_move_pitch"); } else if (action.Contains("yaw")) { m_option = String.Format("flight_move_yaw"); } else { m_option = String.Format("flight_move_roll"); } } } }