using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using Ck_Objects;
using Math3;
using BinTree;

namespace SpriteEditor_2017
{

    /// <summary>
    /// the FrameEditor panel contains controls pertaining to editing the current frame of an animation
    /// </summary>
    public class panelFrameEditor : panelMoveable
    {
        /// <summary>
        /// allows panelFrameEditor to be easily called from anywhere using the command panelFrameEditor.instance
        /// </summary>
        public static panelFrameEditor instance;

        /// <summary>
        /// holds complete list of current sprite's limbs
        /// </summary>
        public ComboBox cmbLimb;
        public Label lblLimb;

        /// <summary>
        /// vertical scrolling panel containing the currently selected limb's various image bitmaps to be selected during frame editing process
        /// </summary>
        public panelScrolling_Vertical pnlScr_LimbImageList = new panelScrolling_Vertical();
        public Label lblLimbImageList_Index = new Label();

        /// <summary>
        /// currently selected limb's angle between itself and its master limb
        /// </summary>
        public TextBox txtHinge_Radians;
        public Label lblHinge_Radians;

        /// <summary>
        /// currently selected limb's SlaveMagnitudeFactor variable controls the distance a limb is draw away from its own master
        /// </summary>
        public TextBox txtHinge_Magnitude;
        public Label lblHinge_Magnitude;

        /// <summary>
        /// currently selected limb's Opacity
        /// </summary>
        public TextBox txtOpacity;
        public Label lblOpacity;

        /// <summary>
        /// currently selected limb's Color Filter
        /// </summary>
        public groupboxColorFilter grbColorFilter;

        /// <summary>
        /// nudFrameCounter determines which frame of the currently selected animation is selected and drawn to the screen
        /// </summary>
        public NumericUpDown nudFrameCounter;
        public Label lblFrameCounter;
        public Label lblFrameCounter_ValueDisplay;

        /// <summary>
        /// label-button UI adds a copy of the currently selected animation frame to the animation immediately after the currently selected frame
        /// </summary>
        public Label lblFrame_Add;

        /// <summary>
        /// label-button UI removes the currently selected frame from the currently selected animation if it is not the only frame in the animation
        /// </summary>
        public Label lblFrame_Sub;

        /// <summary>
        /// label-button UI makes a copy of the currently selected animation frame and holds it in memory to be inserted using the 'insert' frame label-button
        /// </summary>
        public Label lblFrame_Copy;

        /// <summary>
        /// label-button UI inserts that 'copy' UI label-button placed in memory into the currently selected animation immediately after the currently selected frame
        /// </summary>
        public Label lblFrame_Insert;

        /// <summary>
        /// determines whether this frame of the currently selected animation is drawn in a horizontal mirror reflection of itself
        /// </summary>
        public CheckBox chkMirror_Horizontal;

        /// <summary>
        ///  determiens whether this frame of the currently selected animation is drawn in a vertical mirror reflection of itself
        /// </summary>
        public CheckBox chkMirror_Vertical;

        /// <summary>
        /// sets which limb positions the sprite on the screen - the sprite's animation will evolve with the DrawRelativeToLimb stationary on the screen
        /// </summary>
        public ComboBox cmbDrawRelativeToLimb;

        /// <summary>
        /// enables/disables drawRelativeToLimb sprite option
        /// </summary>
        public CheckBox chkDrawRelativeToLimb_EditorToggle = new CheckBox();

        /// <summary>
        /// when checked stepping/running the animation will carry the currently selected LimbTracker limbs's data to the next frame and overwrite their current values with those of the previous frame if chkTrack_Limb_Radians is checked
        /// </summary>
        public CheckedListBox clbLimbTracker_Radians = new CheckedListBox();

        /// <summary>
        /// toggles whether the limbs selected in clbLimbTracker_Radians checkedlistbox are tracked
        /// </summary>
        public CheckBox chkTrack_Limb_Radians = new CheckBox();

        /// <summary>
        /// when checked stepping/running the animation will carry the currently selected LimbTracker limbs's data to the next frame and overwrite their current values with those of the previous frame if chkTrack_Limb_Magnitude is checked
        /// </summary>
        public CheckedListBox clbLimbTracker_Magnitude = new CheckedListBox();

        /// <summary>
        /// toggles whether the limbs selected in clbLimbTracker_Magnitude checkedlistbox are tracked
        /// </summary>
        public CheckBox chkTrack_Limb_Magnitude = new CheckBox();

        Size szLimbTrackerFont = new Size();

        /// <summary>
        /// when checked the current frame's DrawList overwrites all frames drawn using either step or run animation controls
        /// </summary>
        public CheckBox chkTrack_DrawSequence = new CheckBox();

        /// <summary>
        /// 
        /// </summary>
        public CheckBox chkTrack_Override = new CheckBox();

        /// <summary>
        /// when checked the current frame's V-mirror and H-mirror values are over written on all frames drawn using step or run animation controls
        /// </summary>
        public CheckBox chkTrack_Mirrors = new CheckBox();

        /// <summary>
        /// when checked the current frame's DrawRelativeToLimb overwrites the its value over that of all frames drawn using either run or step animation controls
        /// </summary>
        public CheckBox chkTrack_DrawRelativeTo = new CheckBox();

        /// <summary>
        /// when checked the mouse can be used to position limbs on the screen graphically
        /// </summary>
        public CheckBox chkMouse_LimbControl = new CheckBox();

        /// <summary>
        /// pointer to the frame which the panelFrameEditor holds in memory when 'copy' command is pressed
        /// </summary>
        public classAnimation_Frame cFrame_Copy = null;

        /// <summary>
        /// instantiates panelFrameEditor with the standard font
        /// </summary>
        public panelFrameEditor() { Init(fntStandard); }

        /// <summary>
        /// instantiates panelFrameEditor with specified font
        /// </summary>
        /// <param name="fnt">font used to draw the panel's header text</param>
        public panelFrameEditor(Font fnt)
        {
            instance = this;
            Init(fnt);
        }

        bool bolEnableControls = true;
        /// <summary>
        /// toggles frame editing controls - used when running an animation to prevent unwanted tampering with frame data during animation run-time
        /// </summary>
        public bool EnableControls
        {
            get { return bolEnableControls; }
            set
            {
                bolEnableControls = value;
                chkTrack_DrawRelativeTo.Enabled
                     = chkTrack_DrawSequence.Enabled
                     = chkTrack_Override.Enabled
                     = chkTrack_Limb_Radians.Enabled
                     = chkTrack_Mirrors.Enabled
                     = chkMouse_LimbControl.Enabled
                     = chkMirror_Horizontal.Enabled
                     = chkMirror_Vertical.Enabled
                     = lblFrame_Add.Enabled
                     = lblFrame_Sub.Enabled
                     = lblFrame_Copy.Enabled
                     = lblFrame_Insert.Enabled
                     = cmbDrawRelativeToLimb.Enabled
                     = cmbLimb.Enabled
                     = nudFrameCounter.Enabled
                     = pnlScr_LimbImageList.Enabled
                     = bolEnableControls;
            }
        }

        /// <summary>
        /// delays erasing TrackLimbs checkedListBox long enough for mouse to enter control which disables this timer until mouse leaves both label-button and checkedListBox
        /// </summary>
        Timer tmrTrackLimbs_Radians_Hide = new Timer();
        Timer tmrTrackLimbs_Magnitude_Hide = new Timer();

        classSpriteData cSpriteData;
        /// <summary>
        /// setting the current sprite value to a new sprite forces the panelFrameEditor to reinitialize its data to reflect the state of the currently loaded sprite
        /// </summary>
        public classSprite cSprite
        {
            get { return cSpriteData.cAnimationData.cSprite; }
            set
            {
                cSpriteData.cAnimationData.cSprite = value;
                formSpriteEditor_2017.instance.pnlLimb_SetAnimation.SetObjects();
                if (value != null)
                {
                    clbLimbTracker_Init();
                }
            }
        }

        /// <summary>
        /// initializes panelFrameEditor's controls
        /// </summary>
        /// <param name="fnt"></param>
        void Init(Font fnt)
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;

            ContextMenu = formSpriteEditor_2017.instance.cMnuPic;

            lblLimb = formSpriteEditor_2017.instance.lblLimb;
            lblLimb.Name = "lblLimb";
            cmbLimb = formSpriteEditor_2017.instance.cmbLimbs;
            cmbLimb.Name = "cmbLimb";

            lblHinge_Radians = formSpriteEditor_2017.instance.lblHinge_Radians;
            lblHinge_Radians.Name = "lblHinge_Radians";
            txtHinge_Radians = formSpriteEditor_2017.instance.txtHinge_Radians;
            txtHinge_Radians.Name = "txtHinge_Radians";

            lblHinge_Magnitude = formSpriteEditor_2017.instance.lblHinge_Magnitude;
            lblHinge_Magnitude.Name = "lblHinge_Magnitude";

            txtHinge_Magnitude = formSpriteEditor_2017.instance.txtHinge_Magnitude;
            txtHinge_Magnitude.Name = "txtHinge_Magnitude";

            txtOpacity = formSpriteEditor_2017.instance.txtOpacity;
            txtOpacity.Name = "txtOpacity";
            lblOpacity = formSpriteEditor_2017.instance.lblOpacity;
            lblOpacity.Name = "lblOpacity";


            grbColorFilter = formSpriteEditor_2017.instance.grbColorFilter;
            grbColorFilter.Name = "grbColorFilter";

            lblFrameCounter = formSpriteEditor_2017.instance.lblFrame_Counter;
            lblFrameCounter.Name = "lblFrameCounter";

            nudFrameCounter = formSpriteEditor_2017.instance.nudFrame_Counter;
            nudFrameCounter.MouseWheel += formSpriteEditor_2017.instance.nudFrameCounter_MouseWheel;
            nudFrameCounter.Name = "nudFrameCounter";

            lblFrameCounter_ValueDisplay = formSpriteEditor_2017.instance.lblFrameCounter_ValueDisplay;
            lblFrameCounter.Name = "lblFrameCounter";

            lblFrame_Add = formSpriteEditor_2017.instance.lblFrame_Add;
            lblFrame_Add.Name = "lblFrame_Add";

            lblFrame_Sub = formSpriteEditor_2017.instance.lblFrame_Sub;
            lblFrame_Sub.Name = "lblFrame_Sub";

            lblFrame_Copy = formSpriteEditor_2017.instance.lblFrame_Copy;
            lblFrame_Copy.Name = "lblFrame_Copy";
            lblFrame_Insert = formSpriteEditor_2017.instance.lblFrame_Insert;
            lblFrame_Insert.Name = "lblFrame_Insert";

            chkMirror_Horizontal = formSpriteEditor_2017.instance.chkFrame_Mirror_Horizontal;
            chkMirror_Horizontal.Name = "chkMirror_Horizontal";

            chkMirror_Vertical = formSpriteEditor_2017.instance.chkFrame_Mirror_Vertical;
            chkMirror_Vertical.Name = "chkMirror_Vertical";

            cmbDrawRelativeToLimb = formSpriteEditor_2017.instance.cmbFrame_DrawRelativeTo;
            cmbDrawRelativeToLimb.Name = "cmbDrawRelativeToLimb";

            Heading.Font = fnt;
            Heading.Text = "Frame Editor";
            Heading.BackColor
                = pnlContainer.BackColor
                = Color.Orange;
            Heading.ForeColor
                = pnlContainer.ForeColor
                = Color.Black;

            lblLimb.BackColor
                 = cmbLimb.BackColor

                 = lblLimbImageList_Index.BackColor

                 = lblHinge_Radians.BackColor
                 = txtHinge_Radians.BackColor

                 = lblHinge_Magnitude.BackColor
                 = txtHinge_Magnitude.BackColor

                 = lblOpacity.BackColor
                 = txtOpacity.BackColor

                 = grbColorFilter.BackColor

                 = lblFrameCounter.BackColor
                 = nudFrameCounter.BackColor
                 = lblFrameCounter_ValueDisplay.BackColor

                 = lblFrame_Add.BackColor
                 = lblFrame_Sub.BackColor
                 = chkTrack_DrawSequence.BackColor
                 = chkTrack_Override.BackColor
                 = chkTrack_Mirrors.BackColor
                 = chkTrack_DrawRelativeTo.BackColor
                 = chkMouse_LimbControl.BackColor

                 = lblFrame_Copy.BackColor
                 = lblFrame_Insert.BackColor

                 = chkMirror_Horizontal.BackColor
                 = chkMirror_Vertical.BackColor

                 = chkDrawRelativeToLimb_EditorToggle.BackColor
                 = cmbDrawRelativeToLimb.BackColor
                 = clbLimbTracker_Radians.BackColor
                 = chkTrack_Limb_Radians.BackColor
                 = clbLimbTracker_Magnitude.BackColor
                 = chkTrack_Limb_Magnitude.BackColor
                 = pnlContainer.BackColor;

            lblLimb.ForeColor
                  = cmbLimb.ForeColor

                  = lblLimbImageList_Index.ForeColor

                  = lblHinge_Radians.ForeColor
                  = txtHinge_Radians.ForeColor

                  = lblHinge_Magnitude.ForeColor
                  = txtHinge_Magnitude.ForeColor

                  = lblOpacity.ForeColor 
                  = txtOpacity.ForeColor 
                  = grbColorFilter.ForeColor 

                  = lblFrameCounter.ForeColor
                  = nudFrameCounter.ForeColor
                  = lblFrameCounter_ValueDisplay.ForeColor

                  = lblFrame_Add.ForeColor
                  = lblFrame_Sub.ForeColor
                  = chkTrack_DrawSequence.ForeColor
                  = chkTrack_Override.ForeColor
                  = chkTrack_Mirrors.ForeColor
                  = chkTrack_DrawRelativeTo.ForeColor
                  = chkMouse_LimbControl.ForeColor

                  = lblFrame_Copy.ForeColor
                  = lblFrame_Insert.ForeColor

                  = chkMirror_Horizontal.ForeColor
                  = chkMirror_Vertical.ForeColor

                  = chkDrawRelativeToLimb_EditorToggle.ForeColor
                  = cmbDrawRelativeToLimb.ForeColor
                  = clbLimbTracker_Radians.ForeColor
                  = chkTrack_Limb_Radians.ForeColor
                  = clbLimbTracker_Magnitude.ForeColor
                  = chkTrack_Limb_Magnitude.ForeColor
                  = pnlContainer.ForeColor;

            tmrTrackLimbs_Radians_Hide.Interval = 100;
            tmrTrackLimbs_Radians_Hide.Tick += tmrTrackLimbs_Radians_Hide_Tick;

            tmrTrackLimbs_Magnitude_Hide.Interval = 100;
            tmrTrackLimbs_Magnitude_Hide.Tick += tmrTrackLimbs_Magnitude_Hide_Tick;

            lblLimbImageList_Index.Text = "Limb Image";
            lblLimbImageList_Index.Name = "lblLimbImageList_Index";
            lblLimbImageList_Index.AutoSize = false;
            lblLimbImageList_Index.Height = lblFrame_Add.Height;
            lblLimbImageList_Index.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblLimbImageList_Index.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblLimbImageList_Index.Click += LblLimbImageList_Index_Click;
            pnlContainer.Controls.Add(lblLimbImageList_Index);

            pnlScr_LimbImageList.MouseWheel += PnlScr_LimbImageList_MouseWheel;
            pnlScr_LimbImageList.Name = "pnlScr_LimbImageList";
            pnlContainer.Controls.Add(pnlScr_LimbImageList);

            pnlContainer.Controls.Add(chkTrack_DrawSequence);
            chkTrack_DrawSequence.Text = "Track Draw Sequence";
            chkTrack_DrawSequence.Name = "chkTrack_DrawSequence";
            chkTrack_DrawSequence.AutoSize = false;
            chkTrack_DrawSequence.CheckedChanged += chkTrack_CheckedChange;

            pnlContainer.Controls.Add(chkTrack_Override);
            chkTrack_Override.Text = "Track Override";
            chkTrack_Override.Name = "chkTrack_Override";
            chkTrack_Override.AutoSize = false;
            chkTrack_Override.CheckedChanged += chkTrack_CheckedChange;

            pnlContainer.Controls.Add(chkTrack_Mirrors);
            chkTrack_Mirrors.Text = "Track Mirrors";
            chkTrack_Mirrors.Name = "chkTrack_Mirrors";
            chkTrack_Mirrors.AutoSize = false;
            chkTrack_Mirrors.CheckedChanged += chkTrack_CheckedChange;

            pnlContainer.Controls.Add(chkTrack_DrawRelativeTo);
            chkTrack_DrawRelativeTo.Text = "Track Relative To";
            chkTrack_DrawRelativeTo.Name = "chkTrack_DrawRelativeTo";
            chkTrack_DrawRelativeTo.AutoSize = false;
            chkTrack_DrawRelativeTo.CheckedChanged += chkTrack_CheckedChange;


            pnlContainer.Controls.Add(chkMouse_LimbControl);
            chkMouse_LimbControl.Text = "Mouse Limb Control";
            chkMouse_LimbControl.Name = "chkMouse_LimbControl";
            chkMouse_LimbControl.AutoSize = false;
            chkMouse_LimbControl.CheckedChanged += chkTrack_CheckedChange;

            chkTrack_Limb_Radians.Text = "Track Radians";
            chkTrack_Limb_Radians.Name = "chkTrack_Limb_Radians";
            chkTrack_Limb_Radians.CheckedChanged += chkTrack_Limb_Radians_CheckedChanged;
            chkTrack_Limb_Radians.CheckedChanged += chkTrack_CheckedChange;
            chkTrack_Limb_Radians.MouseEnter += clbLimbTracker_Radians_MouseEnter;
            chkTrack_Limb_Radians.MouseLeave += clbLimbTracker_Radians_MouseLeave;
            pnlContainer.Controls.Add(chkTrack_Limb_Radians);

            clbLimbTracker_Radians.ScrollAlwaysVisible = false;
            szLimbTrackerFont = TextRenderer.MeasureText("font", clbLimbTracker_Radians.Font);

            clbLimbTracker_Radians.Name = "clbLimbTracker_Radians";
            clbLimbTracker_Radians.Height = szLimbTrackerFont.Height * 2;
            clbLimbTracker_Radians.BorderStyle = BorderStyle.None;
            clbLimbTracker_Radians.RightToLeft = RightToLeft.No;
            clbLimbTracker_Radians.Visible = chkTrack_Limb_Radians.Checked;
            clbLimbTracker_Radians.CheckOnClick = true;
            clbLimbTracker_Radians.BackColor = Color.Yellow;
            clbLimbTracker_Radians.MouseEnter += clbLimbTracker_Radians_MouseEnter;
            clbLimbTracker_Radians.MouseLeave += clbLimbTracker_Radians_MouseLeave;

            chkTrack_Limb_Magnitude.Text = "Magnitude";
            chkTrack_Limb_Magnitude.Name = "chkTrack_Limb_Magnitude";
            chkTrack_Limb_Magnitude.CheckedChanged += chkTrack_Limb_Magnitude_CheckedChanged;
            chkTrack_Limb_Magnitude.CheckedChanged += chkTrack_CheckedChange;
            chkTrack_Limb_Magnitude.MouseEnter += clbLimbTracker_Magnitude_MouseEnter;
            chkTrack_Limb_Magnitude.MouseLeave += clbLimbTracker_Magnitude_MouseLeave;
            pnlContainer.Controls.Add(chkTrack_Limb_Magnitude);

            clbLimbTracker_Magnitude.ScrollAlwaysVisible = false;
            szLimbTrackerFont = TextRenderer.MeasureText("font", clbLimbTracker_Magnitude.Font);
            clbLimbTracker_Magnitude.Name = "clbLimbTracker_Magnitude";
            clbLimbTracker_Magnitude.Height = szLimbTrackerFont.Height * 2;
            clbLimbTracker_Magnitude.BorderStyle = BorderStyle.None;
            clbLimbTracker_Magnitude.Visible = chkTrack_Limb_Magnitude.Checked;
            clbLimbTracker_Magnitude.CheckOnClick = true;
            clbLimbTracker_Magnitude.BackColor = Color.Yellow;
            clbLimbTracker_Magnitude.MouseEnter += clbLimbTracker_Magnitude_MouseEnter;
            clbLimbTracker_Magnitude.MouseLeave += clbLimbTracker_Magnitude_MouseLeave;

            pnlContainer.Controls.Add(chkMirror_Horizontal);
            pnlContainer.Controls.Add(chkMirror_Vertical);

            pnlContainer.Controls.Add(lblLimb);
            pnlContainer.Controls.Add(cmbLimb);

            pnlContainer.Controls.Add(lblHinge_Radians);
            pnlContainer.Controls.Add(txtHinge_Radians);

            pnlContainer.Controls.Add(lblHinge_Magnitude);
            pnlContainer.Controls.Add(txtHinge_Magnitude);

            pnlContainer.Controls.Add(lblOpacity);
            pnlContainer.Controls.Add(txtOpacity);

            pnlContainer.Controls.Add(grbColorFilter);

            pnlContainer.Controls.Add(lblFrameCounter);
            pnlContainer.Controls.Add(nudFrameCounter);
            pnlContainer.Controls.Add(lblFrameCounter_ValueDisplay);

            pnlContainer.Controls.Add(lblFrame_Add);
            pnlContainer.Controls.Add(lblFrame_Sub);

            pnlContainer.Controls.Add(lblFrame_Copy);
            pnlContainer.Controls.Add(lblFrame_Insert);

            chkDrawRelativeToLimb_EditorToggle.Name = "chkDrawRelativeToLimb_EditorToggle";
            chkDrawRelativeToLimb_EditorToggle.Appearance = Appearance.Button;
            chkDrawRelativeToLimb_EditorToggle.AutoSize = false;
            chkDrawRelativeToLimb_EditorToggle.CheckStateChanged += ChkDrawRelativeToLimb_EditorToggle_CheckStateChanged;
            chkDrawRelativeToLimb_EditorToggle_setColor();
            pnlContainer.Controls.Add(chkDrawRelativeToLimb_EditorToggle);

            cmbDrawRelativeToLimb.Name = "cmbDrawRelativeToLimb";
            pnlContainer.Controls.Add(cmbDrawRelativeToLimb);

            pnlContainer.Controls.Add(clbLimbTracker_Radians);
            pnlContainer.Controls.Add(clbLimbTracker_Magnitude);

            lblFrame_Add.MouseEnter += lbl_MouseEnter;
            lblFrame_Add.MouseLeave += lbl_MouseLeave;

            lblFrame_Sub.MouseEnter += lbl_MouseEnter;
            lblFrame_Sub.MouseLeave += lbl_MouseLeave;

            lblFrame_Copy.MouseEnter += lbl_MouseEnter;
            lblFrame_Copy.MouseLeave += lbl_MouseLeave;

            lblFrame_Insert.MouseEnter += lbl_MouseEnter;
            lblFrame_Insert.MouseLeave += lbl_MouseLeave;

            lblLimbImageList_Index.MouseEnter += lbl_MouseEnter;
            lblLimbImageList_Index.MouseLeave += lbl_MouseLeave;

            init_Format();

            setToolTip();

            cSpriteData.cAnimationData.cSprite = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite;

            SizeChanged += panelFrameEditor_SizeChanged;
            LocationChanged += panelFrameEditor_LocationChanged;
            Disposed += panelFrameEditor_Disposed;
        }

        public void init_Format()
        {  // sets panelFrameEditor's format information
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].size_Height);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].ExpansionDirection;
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolIgnoreChanges = false;

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.FrameEditor_Track_DrawSequence_checked] != null)
                chkTrack_DrawSequence.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.FrameEditor_Track_DrawSequence_checked]);
            else
                chkTrack_DrawSequence.Checked = false;

            //if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.FrameEditor_Track_Override_checked] != null)
            //    chkTrack_Override.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.FrameEditor_Track_Override_checked]);
            //else
            //    chkTrack_Override.Checked = false;

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Track_Mirrors_checked] != null)
                chkTrack_Mirrors.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Track_Mirrors_checked]);
            else
                chkTrack_Mirrors.Checked = false;

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Track_DrawRelativeTo_checked] != null)
                chkTrack_DrawRelativeTo.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Track_DrawRelativeTo_checked]);
            else
                chkTrack_DrawRelativeTo.Checked = false;

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_LimbMouseController_checked] != null)
                chkMouse_LimbControl.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_LimbMouseController_checked]);
            else
                chkMouse_LimbControl.Checked = false;


            placeObjects();
        }

        /// <summary>
        /// binds panelFrameEditor's controls to formSpriteEditor_2017's tooltip
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;

            // panelFrameEditor
            string strCmbLimb = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblLimb, strCmbLimb);
            tt.SetToolTip(cmbLimb, strCmbLimb);

            string strLimbImageList = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblLimbImageList_Index, strLimbImageList);
            tt.SetToolTip(pnlScr_LimbImageList, strLimbImageList);

            string strHingeRadians = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblHinge_Radians, strHingeRadians);
            tt.SetToolTip(txtHinge_Radians, strHingeRadians);

            string strHingeMagnitude = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblHinge_Magnitude, strHingeMagnitude);
            tt.SetToolTip(txtHinge_Magnitude, strHingeMagnitude);

            string strOpacity = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblOpacity, strOpacity);
            tt.SetToolTip(txtOpacity, strOpacity);

            tt.SetToolTip(grbColorFilter, formSpriteEditor_2017.conDefaultToolTip);

            string strFrameCounter = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblFrameCounter, strFrameCounter);
            tt.SetToolTip(nudFrameCounter, strFrameCounter);
            tt.SetToolTip(lblFrameCounter_ValueDisplay, strFrameCounter);

            tt.SetToolTip(lblFrame_Add, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblFrame_Sub, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblFrame_Copy, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblFrame_Insert, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(chkMirror_Horizontal, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkMirror_Vertical, formSpriteEditor_2017.conDefaultToolTip);

            string strDrawRelativeTo = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(cmbDrawRelativeToLimb, strDrawRelativeTo);
            tt.SetToolTip(chkDrawRelativeToLimb_EditorToggle, strDrawRelativeTo);

            string strLimbTracker = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(clbLimbTracker_Radians, strLimbTracker);
            tt.SetToolTip(chkTrack_Limb_Radians, strLimbTracker);

            tt.SetToolTip(chkTrack_DrawSequence, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkTrack_Override, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkTrack_Mirrors, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkTrack_DrawRelativeTo, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkMouse_LimbControl, formSpriteEditor_2017.conDefaultToolTip);


        }

        classSprite_Limb cLimbRelTo_Prev = null;
        /// <summary>
        /// toggling checkbox DrawRelativeToLimb_Editor moves sprite's position on screen
        /// </summary>
        private void ChkDrawRelativeToLimb_EditorToggle_CheckStateChanged(object sender, EventArgs e)
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            chkDrawRelativeToLimb_EditorToggle_setColor();

            if (cSpriteData != null
                && cSpriteData.cAnimationData.cAnimation != null)
            {
                classAnimation_Frame cFrame = cSpriteData.cAnimationData.cAnimation.lstFrames[cSpriteData.cAnimationData.intFrameIndex];

                classSprite_Limb cLimbRelativeTo = cSprite.cCostumeInfo_Default.lstLimbs[cFrame.Limb_DrawRelativeTo];

                Point ptDiff = classMath3.SubTwoPoints(formSpriteEditor_2017.instance.ptDraw_DrawRel_Off, cSpriteData.pt);

                if (cLimbRelativeTo != null && (ptDiff.X != 0 || ptDiff.Y != 0))
                {
                    Point ptShift = cLimbRelativeTo.ptDrawCenter;
                    if (false && cLimbRelTo_Prev != null)
                    {
                        ptShift = classMath3.SubTwoPoints(ptShift, cLimbRelTo_Prev.ptDrawCenter);
                        cLimbRelTo_Prev = cLimbRelativeTo;
                    }

                    if (chkDrawRelativeToLimb_EditorToggle.Checked)
                    {
                        cSpriteData.pt = classMath3.AddTwoPoints(cSpriteData.pt, ptShift);

                        formSpriteEditor_2017.instance.ptDraw_DrawRel_Off = classMath3.SubTwoPoints(cSpriteData.pt, ptShift);
                    }
                    else
                    {
                        cSpriteData.pt = classMath3.SubTwoPoints(cSpriteData.pt, ptShift);
                        formSpriteEditor_2017.instance.ptDraw_DrawRel_Off = classMath3.AddTwoPoints(cSpriteData.pt, ptShift);

                    }

                    formSpriteEditor_2017.instance.tmrFocusDelta.Enabled = true;
                }
                formSpriteEditor_2017.instance.Draw_Sprite();
            }
        }

        /// <summary>
        /// sets the color of the control chkDrawRelativeToLimb_Editor to reflect its current state
        /// </summary>
        public void chkDrawRelativeToLimb_EditorToggle_setColor()
        {
            chkDrawRelativeToLimb_EditorToggle.ForeColor = chkDrawRelativeToLimb_EditorToggle.Checked
                                                                    ? pnlContainer.ForeColor
                                                                    : pnlContainer.BackColor;

            chkDrawRelativeToLimb_EditorToggle.BackColor = chkDrawRelativeToLimb_EditorToggle.Checked
                                                                    ? pnlContainer.BackColor
                                                                    : pnlContainer.ForeColor;

            string strText = "Draw relative to (Editor Toggle :";
            chkDrawRelativeToLimb_EditorToggle.Text = strText + (chkDrawRelativeToLimb_EditorToggle.Checked ? "On" : "Off") + ")";

        }

        /// <summary>
        /// scrolling vertical panel displays the currently selected limb's image selections
        /// </summary>
        public void PnlScr_LimbImageList_MouseWheel(object sender, MouseEventArgs e)
        {
            ScrollEventType scEventType = e.Delta < 0
                                                  ? ScrollEventType.SmallIncrement
                                                  : ScrollEventType.SmallDecrement;

            ScrollEventArgs scEventArgs = new ScrollEventArgs(scEventType, pnlScr_LimbImageList.vsb.Value + e.Delta);
            pnlScr_LimbImageList.Scroll(sender, scEventArgs);
        }

        /// <summary>
        /// colors label under mouse to its default color when mouse leaves control
        /// </summary>
        private void lbl_MouseLeave(object sender, EventArgs e)
        {
            Label lblSender = (Label)sender;
            lblSender.BackColor = pnlContainer.BackColor;
            lblSender.ForeColor = pnlContainer.ForeColor;
        }

        /// <summary>
        /// colors label under mouse to its highlight color when mouse enters control
        /// </summary>
        private void lbl_MouseEnter(object sender, EventArgs e)
        {
            Label lblSender = (Label)sender;
            lblSender.BackColor = pnlContainer.ForeColor;
            lblSender.ForeColor = pnlContainer.BackColor;
        }

        /// <summary>
        /// hides the LimbImageList scrolling panel when the mouse cursor leaves
        /// </summary>
        public void PnlScr_LimbImageList_MouseLeave(object sender, EventArgs e)
        {
            if (!pnlContainer.Contains(pnlScr_LimbImageList))
            {
                pnlContainer.Controls.Add(pnlScr_LimbImageList);
            }

            pnlScr_LimbImageList.Hide();
        }

        /// <summary>
        /// draws the scrolling panel containing the various limb images available for selection in the current animation frame
        /// </summary>
        private void LblLimbImageList_Index_Click(object sender, EventArgs e)
        {
            classSprite_Limb cLimb = formSpriteEditor_2017.instance.cLimb;
            pnlScr_LimbImageList_Init(ref cLimb);
            pnlScr_LimbImageList.BackColor = Color.White;
            pnlScr_LimbImageList.Visible = true;
            pnlScr_LimbImageList.BringToFront();
        }

        /// <summary>
        /// hides the LimbTracker checkedlistbox after mouse leaves
        /// </summary>
        private void tmrTrackLimbs_Radians_Hide_Tick(object sender, EventArgs e)
        {
            clbLimbTracker_Radians.Height = 2;
            tmrTrackLimbs_Radians_Hide.Enabled = false;
        }

        /// <summary>
        /// hides the LimbTracker checkedlistbox after mouse leaves
        /// </summary>
        private void tmrTrackLimbs_Magnitude_Hide_Tick(object sender, EventArgs e)
        {
            clbLimbTracker_Magnitude.Height = 2;
            tmrTrackLimbs_Magnitude_Hide.Enabled = false;
        }

        /// <summary>
        /// draws the Track checkbox calling to reflect its checked condition
        /// </summary>
        private void chkTrack_CheckedChange(object sender, EventArgs e)
        {
            CheckBox chkSender = (CheckBox)sender;
            chkSender.BackColor = chkSender.Checked
                                           ? Color.Yellow
                                           : pnlContainer.BackColor;
        }

        /// <summary>
        /// displays the checkedListBox with LimbTracker list if its checkbox is checked
        /// </summary>
        private void chkTrack_Limb_Radians_CheckedChanged(object sender, EventArgs e)
        {
            clbLimbTracker_Radians.Visible = chkTrack_Limb_Radians.Checked;
            if (chkTrack_Limb_Radians.Checked)
            {
                clbLimbTracker_Radians.BringToFront();
                clbLimbTracker_Radians_SetSize();
            }
            else
            {
                clbLimbTracker_Radians.SendToBack();
            }

        }

        /// <summary>
        /// triggers timer that will hide the checkedListBox showing the LimbTracker data
        /// </summary>
        private void clbLimbTracker_Radians_MouseLeave(object sender, EventArgs e)
        {
            tmrTrackLimbs_Radians_Hide.Enabled = true;
        }

        /// <summary>
        /// disables timer that would have hidden checkedListBox showing the LimbTracker data
        /// </summary>
        private void clbLimbTracker_Radians_MouseEnter(object sender, EventArgs e)
        {
            tmrTrackLimbs_Radians_Hide.Enabled = false;
            clbLimbTracker_Radians_SetSize();
        }

        /// <summary>
        /// resizes LimbTracker checkedListBox to fit inside panel containing it without exceeding the natural size of its content
        /// </summary>
        void clbLimbTracker_Radians_SetSize()
        {
            if (chkTrack_Limb_Radians.Checked)
            {
                int intItemHeight = clbLimbTracker_Radians.Items.Count > 0
                                                               ? clbLimbTracker_Radians.GetItemHeight(0)
                                                               : clbLimbTracker_Radians.Font.Height;
                int intHeight = intItemHeight * clbLimbTracker_Radians.Items.Count;
                if (clbLimbTracker_Radians.Top + intHeight > pnlContainer.Bottom)
                    intHeight = pnlContainer.Bottom - clbLimbTracker_Radians.Top - 2;
                clbLimbTracker_Radians.Height = intHeight;

                clbLimbTracker_Radians.BringToFront();
            }
        }


        /// <summary>
        /// displays the checkedListBox with LimbTracker list if its checkbox is checked
        /// </summary>
        private void chkTrack_Limb_Magnitude_CheckedChanged(object sender, EventArgs e)
        {
            clbLimbTracker_Magnitude.Visible = chkTrack_Limb_Magnitude.Checked;
            if (chkTrack_Limb_Magnitude.Checked)
            {
                clbLimbTracker_Magnitude.BringToFront();
                clbLimbTracker_Magnitude_SetSize();
            }
            else
            {
                clbLimbTracker_Magnitude.SendToBack();
            }

        }

        /// <summary>
        /// triggers timer that will hide the checkedListBox showing the LimbTracker data
        /// </summary>
        private void clbLimbTracker_Magnitude_MouseLeave(object sender, EventArgs e)
        {
            tmrTrackLimbs_Magnitude_Hide.Enabled = true;
        }

        /// <summary>
        /// disables timer that would have hidden checkedListBox showing the LimbTracker data
        /// </summary>
        private void clbLimbTracker_Magnitude_MouseEnter(object sender, EventArgs e)
        {
            tmrTrackLimbs_Magnitude_Hide.Enabled = false;
            clbLimbTracker_Magnitude_SetSize();
        }

        /// <summary>
        /// resizes LimbTracker checkedListBox to fit inside panel containing it without exceeding the natural size of its content
        /// </summary>
        void clbLimbTracker_Magnitude_SetSize()
        {
            if (chkTrack_Limb_Magnitude.Checked)
            {
                int intItemHeight = clbLimbTracker_Magnitude.Items.Count > 0
                                                               ? clbLimbTracker_Magnitude.GetItemHeight(0)
                                                               : clbLimbTracker_Magnitude.Font.Height;
                int intHeight = intItemHeight * clbLimbTracker_Magnitude.Items.Count;
                if (clbLimbTracker_Magnitude.Top + intHeight > pnlContainer.Bottom)
                    intHeight = pnlContainer.Bottom - clbLimbTracker_Magnitude.Top - 2;
                clbLimbTracker_Magnitude.Height = intHeight;

                clbLimbTracker_Magnitude.BringToFront();
            }
        }

        /// <summary>
        /// records panel's formatting information to be used at next load time
        /// </summary>
        private void panelFrameEditor_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].Collapsed = Collapsed;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].ExpansionDirection = ExpansionDirection;
        }

        /// <summary>
        /// records the panel's location for formatting purposes after a location change
        /// </summary>
        private void panelFrameEditor_LocationChanged(object sender, EventArgs e)
        {

            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolInit = true;
            }
        }

        /// <summary>
        /// records panel's size for formatting purposes after a size change event
        /// </summary>
        private void panelFrameEditor_SizeChanged(object sender, EventArgs e)
        {

            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolIgnoreChanges
                && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.FrameEditor].Collapsed = Collapsed;

            placeObjects();
        }

        int intLimbImageList_PanelHeight = 120;
        Point ptLimbImageList_Pic_MousePosition = new Point();
        /// <summary>
        /// initializes the panel displaying the list of images available for the specified limb
        /// </summary>
        /// <param name="cLimb">limb for which the images are to be displayed</param>
        public void pnlScr_LimbImageList_Init(ref classSprite_Limb cLimb)
        {
            pnlScr_LimbImageList.clear();
            PictureBox pic = new PictureBox();
            pic.Dock = DockStyle.Fill;
            pic.Click += Pic_Click;
            pic.MouseLeave += Pic_MouseLeave;
            pic.MouseWheel += Pic_MouseWheel;
            pic.MouseMove += Pic_MouseMove;
            Bitmap bmpPanel = new Bitmap(lblLimbImageList_Index.Width, intLimbImageList_PanelHeight * cLimb.lstImages.Count);
            using (Graphics g = Graphics.FromImage(bmpPanel))
            {
                int intVSB_Width = 25;
                for (int intImageCounter = 0; intImageCounter < cLimb.lstImages.Count; intImageCounter++)
                {
                    classSprite_Limb.classSprite_Limb_Images cLimbImage = cLimb.lstImages[intImageCounter];

                    Bitmap Bmp = (Bitmap)cLimbImage.bmpImages[0];

                    Rectangle recSource = new Rectangle(Math3.classGraphics.ptZero, Bmp.Size);
                    Rectangle recDestination = new Rectangle(new Point(0, intImageCounter * intLimbImageList_PanelHeight), new Size(lblLimbImageList_Index.Width - intVSB_Width, intLimbImageList_PanelHeight));

                    g.FillRectangle(Brushes.White, recDestination);
                    g.DrawRectangle(Pens.Orange, new Rectangle(1, recDestination.Top, recDestination.Width - 2, recDestination.Height - 2));
                    ///////////////////////////////////////////////

                    double dblAspectRatio_Pic = (double)recDestination.Height / (double)(recDestination.Width - intVSB_Width);
                    double dblAspectRatio_Bmp = (double)Bmp.Height / (double)Bmp.Width;

                    Rectangle recBmpSource = new Rectangle(classGraphics.ptZero, Bmp.Size);
                    Rectangle recBmpDestination = new Rectangle();

                    if (dblAspectRatio_Bmp > dblAspectRatio_Pic)
                    { // limiting factor is the height of the picbox
                        recBmpDestination.Width = (int)((double)recDestination.Height / dblAspectRatio_Bmp);
                        recBmpDestination.Height = recDestination.Height;
                        recBmpDestination.Y = recDestination.Top;
                        recBmpDestination.X = (recDestination.Width - intVSB_Width - recDestination.Width) / 2;
                    }
                    else
                    { // limiting factor is the width of the recDestinationbox
                        recBmpDestination.Height = (int)((double)(recDestination.Width - intVSB_Width) * dblAspectRatio_Bmp);
                        recBmpDestination.Width = recDestination.Width - intVSB_Width;
                        recBmpDestination.X = 0;
                        recBmpDestination.Y = recDestination.Top + (recDestination.Height - recBmpDestination.Height) / 2;
                    }

                    g.DrawImage(Bmp, recBmpDestination, recBmpSource, GraphicsUnit.Pixel);

                    Font fnt = new Font("courier", 8, FontStyle.Regular);
                    Size szText = TextRenderer.MeasureText(cLimbImage.Name, fnt);

                    g.DrawString(cLimbImage.Name, fnt, Brushes.Black, recDestination.Location);


                    pic.Image = bmpPanel;
                }
                ///////////////////////////////////////////////


                Panel pnlImageContainer = new Panel();

                pnlImageContainer.Size = bmpPanel.Size;
                pnlImageContainer.Controls.Add(pic);

                pnlScr_LimbImageList.AddPanel(ref pnlImageContainer);
                pnlScr_LimbImageList.PositionPanels();
            }
        }

        /// <summary>
        /// tracks mouse position over the picturebox displaying limb's LimbImage list
        /// </summary>
        private void Pic_MouseMove(object sender, MouseEventArgs e)
        {
            ptLimbImageList_Pic_MousePosition.X = e.X;
            ptLimbImageList_Pic_MousePosition.Y = e.Y;
        }

        /// <summary>
        /// scrolls vertical scrolling panel according to mouseWheel UI
        /// </summary>
        private void Pic_MouseWheel(object sender, MouseEventArgs e)
        {
            ScrollEventType scEventType = e.Delta < 0
                                                 ? ScrollEventType.SmallIncrement
                                                 : ScrollEventType.SmallDecrement;
            ScrollEventArgs scEventArgs = new ScrollEventArgs(scEventType, pnlScr_LimbImageList.vsb.Value + e.Delta);
            pnlScr_LimbImageList.Scroll(sender, scEventArgs);
        }

        /// <summary>
        /// hides the Vertical scrolling panel displaying the list of available limbs images for specified limb
        /// </summary>
        private void Pic_MouseLeave(object sender, EventArgs e)
        {
            pnlScr_LimbImageList.Hide();
        }

        /// <summary>
        /// sets the currently selected limb's image to be drawn in the current animation frame 
        /// </summary>
        private void Pic_Click(object sender, EventArgs e)
        {
            if (pnlScr_LimbImageList.Enabled)
            {
                int intIndex = (int)Math.Floor((double)ptLimbImageList_Pic_MousePosition.Y / (double)intLimbImageList_PanelHeight);
                classSprite_Limb cLimb = formSpriteEditor_2017.instance.cLimb;
                classSprite_Limb.classSprite_Limb_Images cLimbImageList = cLimb.lstImages[intIndex];
                picLimbImage_Selected(ref cLimbImageList);
            }
        }

        /// <summary>
        /// sets the limb selected using the VScrollingPanel displaying the limb's choice of images
        /// </summary>
        /// <param name="cLimbImageSelected">class containing selected image to be set as current limb image</param>
        public void picLimbImage_Selected(ref classSprite_Limb.classSprite_Limb_Images cLimbImageSelected)
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            classSprite_Limb cLimb = formSpriteEditor_2017.instance.cLimb;
            classAnimation cAnimation = cSpriteData.cAnimationData.cAnimation;
            classAnimation_Frame cFrame = cAnimation.lstFrames[cSpriteData.cAnimationData.intFrameIndex];

            classAnimation_Frame_LimbData cData = null;

            cData = cFrame.getData(cLimb.Name);
            if (cData != null)
            {
                int intIndex = cLimb.lstImages.IndexOf(cLimbImageSelected);
                cData.ImageList_Index = intIndex;
                formSpriteEditor_2017.instance.Draw_Sprite();
            }
            pnlScr_LimbImageList.Hide();
            if (panelHingeContact_Graphical.instance.Visible
                && !panelHingeContact_Graphical.instance.Collapsed)
                panelHingeContact_Graphical.instance.setLimbContact(ref cLimb);

        }

        /// <summary>
        /// initializes the LimbTracker checkedListBox to reflect the currently loaded sprite complete list of limbs
        /// </summary>
        public void clbLimbTracker_Init()
        {
            List<classSprite_Limb> lstLimbsTracked = new List<classSprite_Limb>();

            for (int intLimbCounter = 0; intLimbCounter < cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
                lstLimbsTracked.Add(cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter]);

            IEnumerable<classSprite_Limb> query = lstLimbsTracked.OrderBy(limb => limb.Name);
            lstLimbsTracked = (List<classSprite_Limb>)query.ToList<classSprite_Limb>();

            clbLimbTracker_Radians.Items.Clear();
            clbLimbTracker_Radians.RightToLeft = RightToLeft.No;
            for (int intLimbCounter = 0; intLimbCounter < lstLimbsTracked.Count; intLimbCounter++)
            {
                clbLimbTracker_Radians.Items.Add(lstLimbsTracked[intLimbCounter].Name);
            }

            clbLimbTracker_Magnitude.Items.Clear();
            clbLimbTracker_Magnitude.RightToLeft = RightToLeft.Yes;
            for (int intLimbCounter = 0; intLimbCounter < lstLimbsTracked.Count; intLimbCounter++)
            {
                clbLimbTracker_Magnitude.Items.Add(lstLimbsTracked[intLimbCounter].Name);
            }
        }

        /// <summary>
        /// positions controls onto the panel
        /// </summary>
        void placeObjects()
        {
            lblLimb.Left
                = lblLimbImageList_Index.Left
                = lblFrameCounter.Left
                = lblFrame_Copy.Left
                = chkDrawRelativeToLimb_EditorToggle.Left
                = chkTrack_Limb_Radians.Left
                = cmbDrawRelativeToLimb.Left
                = clbLimbTracker_Radians.Left
                = clbLimbTracker_Magnitude.Left
                = lblHinge_Radians.Left
                = lblOpacity.Left
                = 2;

            chkTrack_Limb_Radians.Top
                = chkTrack_Limb_Magnitude.Top
                = 2;

            clbLimbTracker_Radians.Top
                = clbLimbTracker_Magnitude.Top
                = chkTrack_Limb_Radians.Bottom - 6;

            chkTrack_Limb_Radians.Width
                = chkTrack_Limb_Magnitude.Width
                = (pnlContainer.Width - chkTrack_Limb_Radians.Left - 2) / 2;

            clbLimbTracker_Radians.Width
                = clbLimbTracker_Magnitude.Width
                = pnlContainer.Width - chkTrack_Limb_Radians.Left - 2;

            chkTrack_Limb_Magnitude.Left = chkTrack_Limb_Radians.Right;

            clbLimbTracker_Radians.BringToFront();
            clbLimbTracker_Magnitude.BringToFront();
            List<CheckBox> lstCheckBoxes = new List<CheckBox>();

            lstCheckBoxes.Add(chkTrack_Mirrors);
            lstCheckBoxes.Add(chkTrack_DrawSequence);
            lstCheckBoxes.Add(chkTrack_Override);
            lstCheckBoxes.Add(chkTrack_DrawRelativeTo);
            lstCheckBoxes.Add(null);
            lstCheckBoxes.Add(chkMouse_LimbControl);

            for (int intCheckBoxCounter = 0; intCheckBoxCounter < lstCheckBoxes.Count; intCheckBoxCounter++)
            {
                if (lstCheckBoxes[intCheckBoxCounter] != null)
                {
                    lstCheckBoxes[intCheckBoxCounter].Height = 15;
                    lstCheckBoxes[intCheckBoxCounter].BringToFront();
                    lstCheckBoxes[intCheckBoxCounter].Top = chkTrack_Limb_Radians.Bottom + intCheckBoxCounter * lstCheckBoxes[0].Height;
                    lstCheckBoxes[intCheckBoxCounter].Left = 2;
                    lstCheckBoxes[intCheckBoxCounter].Width = pnlContainer.Width - lstCheckBoxes[intCheckBoxCounter].Left - 2;
                }
            }

            lblLimb.Top
                = cmbLimb.Top
                = chkMouse_LimbControl.Bottom + 5;
            cmbLimb.Left = lblLimb.Right + 2;
            cmbLimb.Width = pnlContainer.Width - cmbLimb.Left - 2;

            lblLimbImageList_Index.Top
                = cmbLimb.Bottom + 3;
            lblLimbImageList_Index.Width
                = pnlScr_LimbImageList.Width
                = pnlContainer.Width - 4;
            pnlScr_LimbImageList.Location = new Point(lblLimbImageList_Index.Left, 0);
            pnlScr_LimbImageList.Height = pnlContainer.Height;
            pnlScr_LimbImageList.Hide();
            pnlScr_LimbImageList.SendToBack();

            lblHinge_Radians.Top
                = txtHinge_Radians.Top
                = lblHinge_Magnitude.Top 
                = txtHinge_Magnitude.Top 
                = lblLimbImageList_Index.Bottom + 3;

            txtHinge_Radians.Width
                = txtHinge_Magnitude.Width
                = (pnlContainer.Width - lblHinge_Radians.Width - lblHinge_Magnitude.Width - lblHinge_Radians.Left * 2)/2;

            txtHinge_Radians.Left = lblHinge_Radians.Right;
            lblHinge_Magnitude.Left = txtHinge_Radians.Right;
            txtHinge_Magnitude.Left = lblHinge_Magnitude.Right;

            txtOpacity.Top = txtHinge_Magnitude.Bottom;
            txtOpacity.Left = lblOpacity.Right;
            txtOpacity.Width = pnlContainer.Width - lblOpacity.Right - lblOpacity.Left;

            grbColorFilter.Top = txtOpacity.Bottom;
            grbColorFilter.Left = 2;

            lblFrameCounter.Top
                = nudFrameCounter.Top
                = lblFrameCounter_ValueDisplay.Top
                = lblFrame_Add.Top
                = lblFrame_Sub.Top
                = grbColorFilter.Bottom + 2;
            nudFrameCounter.Left = lblFrameCounter.Right + 2;
            lblFrameCounter_ValueDisplay.Left = nudFrameCounter.Right + 2;

            lblFrame_Sub.Left = pnlContainer.Width - lblFrame_Sub.Width - 2;
            lblFrame_Add.Left = lblFrame_Sub.Left - lblFrame_Add.Width - 2;

            lblFrame_Copy.Top
                = lblFrame_Insert.Top
                = chkMirror_Horizontal.Top
                = chkMirror_Vertical.Top
                = nudFrameCounter.Bottom + 2;
            lblFrame_Insert.Left = lblFrame_Copy.Right + 2;

            chkMirror_Vertical.Left = pnlContainer.Width - 2 - chkMirror_Vertical.Width;
            chkMirror_Horizontal.Left = chkMirror_Vertical.Left - 2 - chkMirror_Horizontal.Width;

            chkDrawRelativeToLimb_EditorToggle.Width = pnlContainer.Width - chkDrawRelativeToLimb_EditorToggle.Left - 2;
            chkDrawRelativeToLimb_EditorToggle.Top
                = chkMirror_Horizontal.Bottom + 2;
            cmbDrawRelativeToLimb.Top = chkDrawRelativeToLimb_EditorToggle.Bottom + 1;
            cmbDrawRelativeToLimb.Width = pnlContainer.Width - cmbDrawRelativeToLimb.Left - 2;
        }

    }

    public class groupboxColorFilter : GroupBox
    {
        TextBox[] txt = new TextBox[3];
        Label[] lbl = new Label[3];
        CheckBox chx = new CheckBox();

        enum enuColors { R, G, B, _NumColors };

        public groupboxColorFilter()
        {
            Text = "Color Filter";

            Controls.Add(chx);
            chx.Text = "Valid";
            chx.AutoSize = true;
            chx.CheckedChanged += Chx_CheckedChanged;

            chx.Location = new Point(5, 15);
            Point pt = new Point(chx.Left, chx.Bottom);
            for (int intColorCounter = 0; intColorCounter < (int)enuColors._NumColors; intColorCounter++)
            {
                enuColors eColor = (enuColors)intColorCounter;

                Label lblNew = new Label();
                Controls.Add(lblNew);
                lblNew.Text = eColor.ToString();
                lblNew.AutoSize = true;
                lbl[intColorCounter] = lblNew;
                lblNew.Location = pt;

                TextBox txtNew = new TextBox();
                Controls.Add(txtNew);
                txtNew.Size = new Size(35, 14);
                txtNew.MouseWheel += formSpriteEditor_2017.txt_Byte_MouseWheel;
                txtNew.TextChanged += TxtNew_TextChanged;
                txtNew.KeyDown += TxtNew_KeyDown;
                txtNew.KeyUp += TxtNew_KeyUp;
                txtNew.Tag = (object)eColor;
                txt[intColorCounter] = txtNew;
                txtNew.Location = new Point(lblNew.Right, lblNew.Top);

                pt.X = txtNew.Right;
            }

            Width = pt.X + 5;
            Height = txt[0].Bottom + 5;
        }

        private void TxtNew_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Left:
                case Keys.Right:
                case Keys.Back:
                case Keys.Home:
                case Keys.End:
                    break;

                case Keys.Enter:
                    setColorFilterToUI();
                    formSpriteEditor_2017.instance.Draw_Sprite();
                    break;

                default:
                    {
                    }
                    break;
            }
        }

        private void TxtNew_KeyDown(object sender, KeyEventArgs e)
        {
            switch(e.KeyCode)
            {
                case Keys.Left:
                case Keys.Right:
                case Keys.Back:
                case Keys.Home:
                case Keys.End:
                case Keys.Delete:
                case Keys.NumPad0:
                case Keys.NumPad1:
                case Keys.NumPad2:
                case Keys.NumPad3:
                case Keys.NumPad4:
                case Keys.NumPad5:
                case Keys.NumPad6:
                case Keys.NumPad7:
                case Keys.NumPad8:
                case Keys.NumPad9:
                    break;

                case Keys.Enter:

                    break;

                default:
                    {
                        string strAllowedKeys = "0123456789";
                        char cKeyPressed = (char)e.KeyValue;
                        if (!strAllowedKeys.Contains(cKeyPressed))
                        {
                            e.SuppressKeyPress = true;
                        }
                    }
                    break;
            }
        }

        private void Chx_CheckedChanged(object sender, EventArgs e)
        {
            if (ColorFilter != null)
                ColorFilter.Valid = chx.Checked;
        }
        void setColorFilterToUI()
        {
            bolIgnoreChanges = true;
            byte[] bytValues = new byte[3];
            bytValues[(int)enuColors.R] = ColorFilter.clr.R;
            bytValues[(int)enuColors.G] = ColorFilter.clr.G;
            bytValues[(int)enuColors.B] = ColorFilter.clr.B;

            for (int intTxtCounter = 0; intTxtCounter < txt.Length; intTxtCounter++)
            {
                TextBox txtTemp = txt[intTxtCounter];

                byte bytValue = 0;
                try
                {
                    bytValue = Convert.ToByte(txtTemp.Text);
                    bytValues[intTxtCounter] = bytValue;

                    txtTemp.Text = bytValue.ToString();
                }
                catch (Exception)
                {
                }
            }

            classSpriteData cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            classAnimation cAnimation = cSpriteData.cAnimationData.cAnimation;
            classAnimation_Frame cAnimationFrame = cAnimation.lstFrames[(int)formSpriteEditor_2017.instance.nudFrame_Counter.Value];
            classSprite_Limb cLimb = formSpriteEditor_2017.instance.cLimb;
            classAnimation_Frame_LimbData cLimbData = cAnimationFrame.getData(cLimb.Name);
            cLimbData.ColorFilter.clr = Color.FromArgb(bytValues[(int)enuColors.R],
                                                       bytValues[(int)enuColors.G],
                                                       bytValues[(int)enuColors.B]);
            cLimbData.ColorFilter.Valid = chx.Checked;
            bolIgnoreChanges = false;
        }


        bool bolIgnoreChanges = false;

        private void TxtNew_TextChanged(object sender, EventArgs e)
        {
            if (bolIgnoreChanges || ColorFilter == null) return;

            setColorFilterToUI();
        }

        classAnimation_Frame_LimbData.classColorFilter _ColorFilter = null;
        public classAnimation_Frame_LimbData.classColorFilter ColorFilter
        {
            get { return _ColorFilter; }
            set
            {
                if (_ColorFilter != value)
                {
                    _ColorFilter = value;
                    SetUIToColorFilter();
                }
            }
        }

        void SetUIToColorFilter()
        {
            bolIgnoreChanges = true;
            {
                if (ColorFilter != null)
                {
                    chx.Checked = ColorFilter.Valid;
                    txt[(int)enuColors.R].Text = ColorFilter.clr.R.ToString();
                    txt[(int)enuColors.G].Text = ColorFilter.clr.G.ToString();
                    txt[(int)enuColors.B].Text = ColorFilter.clr.B.ToString();
                }
            }
            bolIgnoreChanges = false;
        }
    }


}
