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>
    /// panel containing controls relevant to editing/running an animation
    /// </summary>
    public class panelAnimation_Controls : panelMoveable
    {
        public Panel pnlAnimation;
        public classLabelButton lbtnStep;
        public classLabelButton lbtnRun;
        classLabelButton lbtnRunSequence = new classLabelButton();
        classLabelButton lbtnAnimationSequence_Add = new classLabelButton();
        public classMultiButtonPic mbpAnimationSequence = new classMultiButtonPic();

        public Label lblAnimation;
        public ComboBox cmbAnimation;
        Timer tmrReturnHome = new Timer();
        /// <summary>
        /// function declaring an instance of panelAnimation_Control
        /// </summary>
        public panelAnimation_Controls() { Init(panelMoveable.fntStandard); }

        /// <summary>
        /// function declaring an instance of panelAnimation_Control
        /// </summary>
        public panelAnimation_Controls(Font fnt) { Init(fnt); }

        /// <summary>
        /// function initializing controls and variables for the panelAnimation_Controls
        /// </summary>
        void Init(Font fnt)
        {
            Heading.Font = fnt;
            Heading.BackColor = Color.Purple;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                 points forms controls to controls declared in formSpriteEditor_2017
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            pnlAnimation = formSpriteEditor_2017.instance.pnlAnimation_container;
            lblAnimation = formSpriteEditor_2017.instance.lblAnimation;
            lbtnRun = formSpriteEditor_2017.instance.lblFrame_Run;
            lbtnStep = formSpriteEditor_2017.instance.lblFrame_Step;
            cmbAnimation = formSpriteEditor_2017.instance.cmbAnimation;


            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                 sets back/fore colors controls
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            pnlContainer.BackColor
                = lblAnimation.BackColor
                = lbtnStep.BackColor
                = lbtnRun.BackColor
                = lbtnRunSequence.BackColor 
                = lbtnAnimationSequence_Add.BackColor 
                = lblAnimation.BackColor
                = cmbAnimation.BackColor
                = mbpAnimationSequence.BackColor 
                = Heading.BackColor;

            pnlContainer.ForeColor
                = lblAnimation.ForeColor
                = lbtnStep.ForeColor
                = lbtnRun.ForeColor
                = lbtnRunSequence.ForeColor 
                = lbtnAnimationSequence_Add.ForeColor
                = lblAnimation.ForeColor
                = cmbAnimation.ForeColor
                = Heading.ForeColor;

            pnlContainer.Controls.Add(lbtnRunSequence);
            lbtnRunSequence_SetText();
            lbtnRunSequence.AutoSize = true;
            lbtnRunSequence.Click += LbtnRunSequence_Click;

            pnlContainer.Controls.Add(lbtnAnimationSequence_Add);
            lbtnAnimationSequence_Add.Text = "Add";
            lbtnAnimationSequence_Add.AutoSize = true;
            lbtnAnimationSequence_Add.Click += LbtnAnimationSequence_Add_Click;

            pnlContainer.Controls.Add(mbpAnimationSequence);
            mbpAnimationSequence.MultiSelect = true;
            mbpAnimationSequence.CanMoveSelection = true;
            mbpAnimationSequence.Formation = classMultiButtonPic.enuButtonFormation.column;
            mbpAnimationSequence.MouseDown += MbpAnimationSequence_Click;
 
            tmrReturnHome.Interval = 100;
            tmrReturnHome.Tick += TmrReturnHome_Tick;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                             sets events for labels to react to mouseEnter/Leave events
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        
            lblAnimation.MouseLeave += Lbl_MouseLeave;
            cmbAnimation.MouseLeave += CmbAnimation_MouseLeave;
            pnlAnimation.MouseLeave += PnlAnimation_MouseLeave;

            lblAnimation.MouseEnter += Lbl_MouseEnter;
            cmbAnimation.MouseEnter += Cmb_MouseEnter;
            pnlAnimation.MouseEnter += Pnl_MouseEnter;

            pnlContainer.Controls.Add(pnlAnimation);
            pnlAnimation.Dock = DockStyle.Fill;
            Text = "Animation Control";

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                     initialize tooltip
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            setToolTip();


            Init_Format();

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                 declare panel's events
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            SizeChanged += PanelAnimation_Controls_SizeChanged;
            LocationChanged += PanelAnimation_Controls_LocationChanged;
            Disposed += PanelAnimation_Controls_Disposed;
        }
        public void Init_Format()
        { 
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                     set-up panel's format values
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].location_Y);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolIgnoreChanges = false;
        
        }


        void MbpAnimationSequence_Click(object sender, MouseEventArgs e)
        {
            classMultiButtonPic mbpSender = (classMultiButtonPic)sender;
            classMultiButtonPic.classButton cBtn_Clicked = mbpSender.ButtonsUnderMouse;
            if (cBtn_Clicked != null)
            {
                switch (e.Button)
                {
                    case MouseButtons.Right:
                        {
                            if (mbpAnimationSequence.lstButtonsSelected.Count > 0)
                            {
                                string strText = "";
                                for (int intCounter = 0; intCounter < mbpAnimationSequence.lstButtonsSelected.Count; intCounter++)
                                {
                                    classMultiButtonPic.classButton cBtn = (classMultiButtonPic.classButton)mbpAnimationSequence.lstButtonsSelected[intCounter];
                                    strText += "\r\n" + cBtn.Text;
                                }
                                if (MessageBox.Show("Remove Selected animations from sequence : " + strText, "Delete Animations from sequence", MessageBoxButtons.YesNo) == DialogResult.Yes)
                                {
                                    int intIndex = mbpAnimationSequence.ButtonIndex(ref cBtn_Clicked);
                                    if (intIndex >= 0)
                                    {
                                        if (lstAnimationSequence[intIndex] == (classAnimation)cBtn_Clicked.Tag)
                                        {
                                            lstAnimationSequence.RemoveAt(intIndex);
                                        }
                                    }
                                    /*IEnumerable<classMultiButtonPic.classButton> query = mbpAnimationSequence.lstButtonsSelected.OrderBy(btn => btn.Index);
                                    List<classMultiButtonPic.classButton> lstTemp  = (List<classMultiButtonPic.classButton>)query.ToList<classMultiButtonPic.classButton>();
                                    for (int intCounter = lstTemp.Count - 1; intCounter >= 0; intCounter--)
                                    {
                                        if (lstTemp[intCounter].Index >= 0)
                                            lstAnimationSequence.RemoveAt(lstTemp[intCounter].Index);
                                    }*/
                                    mbpAnimationSequence_BuildButtons();
                                }
                            }
                            else 
                            if (MessageBox.Show("Delete this Animation from Sequence?", "Delete from Sequence?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                            {
                                lstAnimationSequence.RemoveAt(cBtn_Clicked.Index);
                                mbpAnimationSequence_BuildButtons();
                            }
                        }
                        break;

                    case MouseButtons.Left:
                        {
                        // //   intSequence_Index = (cBtn_Clicked.Index + lstAnimationSequence.Count -1) % lstAnimationSequence.Count;
                          //  AnimationSequence_Next();
                        }
                        break;
                }
            }
        }

        List<classAnimation> lstAnimationSequence = new List<classAnimation>();
        private void LbtnAnimationSequence_Add_Click(object sender, EventArgs e)
        {
            classAnimation cAnimation_Add = (classAnimation)formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cBT_Animations.Search(cmbAnimation.Text);
            if (cAnimation_Add != null)
            {
                lstAnimationSequence.Add(cAnimation_Add);
                mbpAnimationSequence_BuildButtons();
            }
        }

        Font fntButtons = new Font("Ms Sans-serif", 8);
        void mbpAnimationSequence_BuildButtons()
        {
            Size szMin = new Size();

            for (int intAnimationCounter = 0; intAnimationCounter < lstAnimationSequence.Count; intAnimationCounter++)
            {
                Size szAnimation = TextRenderer.MeasureText(lstAnimationSequence[intAnimationCounter].Name, fntButtons);

                if (szAnimation.Width > szMin.Width)
                    szMin.Width = szAnimation.Width;
                if (szAnimation.Height > szMin.Height)
                    szMin.Height = szAnimation.Height;
            }

            mbpAnimationSequence.ClearButtons();

            for (int intAnimationCounter = 0; intAnimationCounter < lstAnimationSequence.Count; intAnimationCounter++)
            {
                classAnimation cAnimation = lstAnimationSequence[intAnimationCounter];
                classMultiButtonPic.classButton cButton = mbpAnimationSequence.Button_New();
                cButton.Text = cAnimation.Name;
                cButton.AutoSize = false;
                cButton.Size = szMin;
                cButton.Forecolor_Highlight
                    = cButton.Backcolor_Idle
                    = Color.White;
                cButton.Forecolor_Idle
                    = cButton.Backcolor_Highlight
                    = Heading.BackColor;
                cButton.Font = fntButtons;
                cButton.Tag = (object)cAnimation;
            }
            mbpAnimationSequence.placeButtons();
            mbpAnimationSequence.Refresh();
        }

        public void AnimationSequence_Clear()
        {
            mbpAnimationSequence.ClearButtons();
            lstAnimationSequence.Clear();
        }

        public void AnimationSequence_Next()
        {
            if (mbpAnimationSequence.cMap.lstElements.Count == 0) return;
            intSequence_Index = (intSequence_Index + 1) % mbpAnimationSequence.cMap.lstElements.Count;
            classMultiButtonPic.classButton cBtn = (classMultiButtonPic.classButton)mbpAnimationSequence.cMap.lstElements[intSequence_Index].obj;
            formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cAnimation = (classAnimation )cBtn.Tag;
            formSpriteEditor_2017.instance.cmbAnimation.SelectedIndex = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstAnimations.IndexOf(formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cAnimation);
        }

        int intSequence_Index = 0;
        public int AnimationSequence_Index
        { 
        get { return intSequence_Index; }
        }
        private void LbtnRunSequence_Click(object sender, EventArgs e)
        {
            formSpriteEditor_2017.instance.AnimationSequence = !formSpriteEditor_2017.instance.AnimationSequence;
        }

        public void lbtnRunSequence_SetText()
        {
            lbtnRunSequence.Text = "Run Sequence : " + (formSpriteEditor_2017.instance.AnimationSequence ? "On" : "Off");
        }


        /// <summary>
        /// sets FormSpriteEditor_2017's tooltip to recognize this panel's controls
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            tt.SetToolTip(pnlAnimation, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbtnRun, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbtnStep, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblAnimation, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(cmbAnimation, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// ensures mouse cursor is well away from this panel before returning to default location after being called by user context menu
        /// </summary>
        private void TmrReturnHome_Tick(object sender, EventArgs e)
        {
            tmrReturnHome.Enabled = false;
            if (!pnlContainer.Contains(pnlAnimation))
            {
                pnlContainer.Controls.Add(pnlAnimation);
                pnlAnimation.Dock = DockStyle.Fill;
            }
        }

        /// <summary>
        /// enables timer which returns panel to its default location after having been placed under the mouse cursor by user context menu
        /// </summary>
        void  MouseLeave() { tmrReturnHome.Enabled = true; }
        private void PnlAnimation_MouseLeave(object sender, EventArgs e) { MouseLeave(); }
        private void CmbAnimation_MouseLeave(object sender, EventArgs e) { MouseLeave(); }
        private void Lbl_MouseLeave(object sender, EventArgs e) { MouseLeave(); }

        /// <summary>
        /// disables timer which would returns panel to its default location after having been placed under the mouse by the user context menu
        /// </summary>
        void MouseEnter() { tmrReturnHome.Enabled = false; }
        private void Pnl_MouseEnter(object sender, EventArgs e) { MouseEnter(); }
        private void Cmb_MouseEnter(object sender, EventArgs e) { MouseEnter(); }
        private void Lbl_MouseEnter(object sender, EventArgs e) { MouseEnter(); }

        /// <summary>
        /// saves this panel's formatting information before being disposed
        /// </summary>
        private void PanelAnimation_Controls_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].Collapsed = Collapsed;
        }

        /// <summary>
        /// records this panel's current location after a move to be saved as its format information
        /// </summary>
        private void PanelAnimation_Controls_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolInit = true;
            }
        }

        /// <summary>
        /// records this panel's current size after a size change to be saved as its format information
        /// </summary>
        private void PanelAnimation_Controls_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolIgnoreChanges
                     && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationControl].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// positions this panel's controls
        /// </summary>
        void placeObjects()
        {
            cmbAnimation.Width = pnlContainer.Width - cmbAnimation.Left - 2;
            lbtnRunSequence.Location = new Point(5, cmbAnimation.Bottom + 3);
            lbtnAnimationSequence_Add.Location = new Point(lbtnRunSequence.Right + 3, lbtnRunSequence.Top);
            mbpAnimationSequence.Location = new Point(lbtnRunSequence.Left, lbtnRunSequence.Bottom + 3);
            mbpAnimationSequence.Width = pnlContainer.Width - mbpAnimationSequence.Left - 2;
            mbpAnimationSequence.Height = pnlContainer.Height - mbpAnimationSequence.Top - 2;
        }

    }
    
    /// <summary>
    /// panel containing controls relevant to editing/running an animation
    /// </summary>
    public class panelCostume_Selector : panelMoveable
    {
        public classLabelButton lbtnNew = new classLabelButton();
        public classLabelButton lbtnLoad = new classLabelButton();
        public classLabelButton lbtnSave = new classLabelButton();
        public classLabelButton lbtnUnload = new classLabelButton();
        public classLabelButton lbtnRename = new classLabelButton();
        public classLabelButton lbtnResize = new classLabelButton();
        public Label lblCostume = new Label();
        public ComboBox cmbCostume = new ComboBox();
        /// <summary>
        /// function declaring an instance of panelAnimation_Control
        /// </summary>
        public panelCostume_Selector() { Init(panelMoveable.fntStandard); }

        /// <summary>
        /// function declaring an instance of panelAnimation_Control
        /// </summary>
        public panelCostume_Selector(Font fnt) { Init(fnt); }

        /// <summary>
        /// function initializing controls and variables for the panelCostume_Selector
        /// </summary>
        void Init(Font fnt)
        {
            Heading.Font = fnt;
            Heading.BackColor = Color.GreenYellow;
            Heading.ForeColor = Color.Black;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                 sets back/fore colors controls
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            pnlContainer.BackColor
                = lbtnLoad.BackColor 
                = lbtnSave.BackColor 
                = lbtnNew.BackColor 
                = lbtnUnload.BackColor 
                = lbtnResize.BackColor 
                = lbtnRename.BackColor 
                = cmbCostume.BackColor 
                = lblCostume.BackColor 
                = Heading.BackColor;

            pnlContainer.ForeColor
                = lbtnLoad.ForeColor
                = lbtnSave.ForeColor
                = lbtnNew.ForeColor
                = lbtnUnload.ForeColor
                = lbtnResize .ForeColor
                = lbtnRename.ForeColor
                = cmbCostume.ForeColor
                = lblCostume.ForeColor 
                = Heading.ForeColor;

            lbtnLoad.Backcolor_Highlight
                = lbtnSave.Backcolor_Highlight
                = lbtnUnload.Backcolor_Highlight
                = lbtnResize .Backcolor_Highlight
                = lbtnRename.Backcolor_Highlight
                = lbtnNew.Backcolor_Highlight
                = Heading.ForeColor;

            lbtnLoad.Forecolor_Highlight
                = lbtnSave.Forecolor_Highlight
                = lbtnUnload.Forecolor_Highlight
                = lbtnResize .Forecolor_Highlight
                = lbtnRename.Forecolor_Highlight
                = lbtnNew.Forecolor_Highlight
                = Heading.BackColor;
            
            lbtnLoad.Backcolor_Idle
                = lbtnSave.Backcolor_Idle
                = lbtnUnload.Backcolor_Idle
                = lbtnResize .Backcolor_Idle
                = lbtnRename.Backcolor_Idle
                = lbtnNew.Backcolor_Idle
                = Heading.BackColor;

            lbtnLoad.Forecolor_Idle
                = lbtnSave.Forecolor_Idle
                = lbtnUnload.Forecolor_Idle
                = lbtnResize .Forecolor_Idle
                = lbtnRename.Forecolor_Idle
                = lbtnNew.Forecolor_Idle
                = Heading.ForeColor;

            lbtnLoad.AutoSize
                = lbtnSave.AutoSize 
                = lbtnNew.AutoSize
                = lbtnUnload.AutoSize
                = lbtnResize .AutoSize
                = lbtnRename.AutoSize
                = lblCostume.AutoSize 
                = true;

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                             sets events for labels to react to mouseEnter/Leave events
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            pnlContainer.Controls.Add(lbtnLoad); 
            lbtnLoad.Text = "Load";
            lbtnLoad.Click += LbtnLoad_Click;
            
            pnlContainer.Controls.Add(lbtnSave); 
            lbtnSave.Text = "Save";
            lbtnSave.Click += LbtnSave_Click;

            pnlContainer.Controls.Add(lbtnUnload);
            lbtnUnload.Text = "Unload";
            lbtnUnload.Click += LbtnUnload_Click;
            
            pnlContainer.Controls.Add(lbtnResize);
            lbtnResize.Text = "Resize";
            lbtnResize.Click += LbtnResize_Click;
                        
            pnlContainer.Controls.Add(lbtnRename);
            lbtnRename.Text = "Rename";
            lbtnRename.Click += LbtnRename_Click;

            pnlContainer.Controls.Add(lbtnNew);
            lbtnNew.Text = "New";
            lbtnNew.Click += LbtnNew_Click;

            pnlContainer.Controls.Add(lblCostume);
            lblCostume.Text = "Costume";

            pnlContainer.Controls.Add(cmbCostume);
            cmbCostume_Load();
            cmbCostume.SelectedIndexChanged += CmbCostume_SelectedIndexChanged;

            Text = "Costume Selector";


            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                     initialize tooltip
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            setToolTip();

            init_Format();


            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                 declare panel's events
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            SizeChanged += PanelCostume_Selector_SizeChanged;
            LocationChanged += PanelCostume_Selector_LocationChanged;
            Disposed += PanelCostume_Selector_Disposed;
        }

        public void init_Format()
        { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                     set-up panel's format values
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].location_Y);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].bolIgnoreChanges = false;
        }

        public void cmbCostume_Load()
        {
            cmbCostume.Items.Clear();
            if (formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite != null)
            {
                int intSelectedIndex = 0;
                for (int intCostumeCounter = 0; intCostumeCounter < formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo.Count; intCostumeCounter++)
                {
                    cmbCostume.Items.Add(formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo[intCostumeCounter].Name);
                    if (formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo[intCostumeCounter] == formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo)
                        intSelectedIndex = intCostumeCounter;
                }
                if (cmbCostume.Items.Count >0 && intSelectedIndex <cmbCostume.Items.Count )
                cmbCostume.SelectedIndex = intSelectedIndex;
            }
        }

        private void CmbCostume_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbCostume.SelectedIndex >= 0
                && cmbCostume.SelectedIndex < formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo.Count)
            {
                formSpriteEditor_2017.instance.semChangeCostume.WaitOne();

                formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo[cmbCostume.SelectedIndex];
                formSpriteEditor_2017.instance.cLimb = (classSprite_Limb)formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo.cBT_Limbs.Search(formSpriteEditor_2017.instance.cLimb.Name);
                formSpriteEditor_2017.instance.Draw_Sprite();

                panelFrameEditor.instance.nudFrameCounter.Value = 0;

                formSpriteEditor_2017.instance.semChangeCostume.Release();
            }
        }

        private void LbtnNew_Click(object sender, EventArgs e)
        {
            
            formSpriteEditor_2017.instance.pnlMessenger.getName("Name of new Costume", "Enter the name of the new Costume",formSpriteEditor_2017.instance.frmMessenger_UserReply, panelMessenger.enuMessage.Costume_New );

            formSpriteEditor_2017.instance.Message("enter new name for new Costume");
            formSpriteEditor_2017.instance.pnlMessenger.txtUserInput.Focus();
            
            /*
            Ck_Objects.form_GetString frmGetNewName = new Ck_Objects.form_GetString(newNameFromForm);
            frmGetNewName.Text  = "Name of new Costume";
            frmGetNewName.Show();
      
        }

        void newNameFromForm(object sender, EventArgs e)
        {
            form_GetString frmSender = (form_GetString)sender;

            classSprite_CostumeInfo cCostumeInfo_New = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.Copy();
            formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default = cCostumeInfo_New;
            cCostumeInfo_New.Name = frmSender.Text_Input;

            cmbCostume_Load();      */
        }

        private void LbtnUnload_Click(object sender, EventArgs e)
        {
            if (formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo != formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default)
            {
                formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo.Remove(formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo);
                //formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default;
                cmbCostume_Load();
                cmbCostume.SelectedIndex = 0;
            }
        }

        private void LbtnResize_Click(object sender, EventArgs e)
        {
            formSpriteEditor_2017.instance.Costume_Resize();
        }
        
        private void LbtnRename_Click(object sender, EventArgs e)
        {
            if (formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo != formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default)
            {
                formSpriteEditor_2017.instance.pnlMessenger.getName("New name for Costume " + formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo.Name, "Enter the new name for this Costume", formSpriteEditor_2017.instance.frmMessenger_UserReply, panelMessenger.enuMessage.Costume_Rename);

                formSpriteEditor_2017.instance.Message("enter new name for existing Costume " + formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo.Name);
                formSpriteEditor_2017.instance.pnlMessenger.txtUserInput.Focus();
            }
        }

        string CostumeInfoFileFilter
        {
            get { return "CostumeInfo files (*" + classSpriteMaker.conCostumeInfoFileExtension.ToString() + ") | *" + classSpriteMaker.conCostumeInfoFileExtension.ToString() + ""; }
        }

        void LbtnSave_Click(object sender, EventArgs e)
        {
            if (formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo != formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default)
            {
                classSprite_CostumeInfo cCostumeInfo = formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo;

                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Title = "Save sprite(" + cCostumeInfo.SpriteName + ") Costume : " + cCostumeInfo.Name + " as ";
                sfd.Filter = CostumeInfoFileFilter;
                sfd.FileName = cCostumeInfo.SpriteName + "_" + cCostumeInfo.Name + ".lin";
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    classSpriteMaker.instance.Save_CostumeInfo(ref cCostumeInfo, sfd.FileName);
                }
            }
            else
                MessageBox.Show("You are currently working with the sprite's default Costume.\r\nSaving the Sprite will save its default Costume", "Default Costume");
        }

        private void LbtnLoad_Click(object sender, EventArgs e)
        {
            string strFilename = formSpriteEditor_2017.instance.strFilename_Current.Substring(0, formSpriteEditor_2017.instance.strFilename_Current.Length - classSpriteMaker.conSpriteFileExtension3.Length);
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = CostumeInfoFileFilter;
            ofd.Title = "Select Costume for sprite : " + formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.Name;
            ofd.Multiselect = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                for (int intFileCounter = 0; intFileCounter < ofd.FileNames.Length; intFileCounter++)
                {
                    string strLoadFilename = ofd.FileNames[intFileCounter];
                    classSprite_CostumeInfo cCostumeInfo = classSpriteMaker.instance.Load_CostumeInfo(ref formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite, strLoadFilename);
                    formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo = cCostumeInfo;
                }
                cmbCostume_Load();
                cmbCostume.SelectedIndex = 0;
            }

        }

        /// <summary>
        /// sets FormSpriteEditor_2017's tooltip to recognize this panel's controls
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            tt.SetToolTip(lbtnNew, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbtnLoad, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbtnUnload, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(cmbCostume, formSpriteEditor_2017.conDefaultToolTip);
        }

  
        /// <summary>
        /// saves this panel's formatting information before being disposed
        /// </summary>
        private void PanelCostume_Selector_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].Collapsed = Collapsed;
        }

        /// <summary>
        /// records this panel's current location after a move to be saved as its format information
        /// </summary>
        private void PanelCostume_Selector_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector ].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].bolInit = true;
            }
        }

        /// <summary>
        /// records this panel's current size after a size change to be saved as its format information
        /// </summary>
        private void PanelCostume_Selector_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].bolIgnoreChanges
                     && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.CostumeSelector].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// positions this panel's controls
        /// </summary>
        void placeObjects()
        {
            lblCostume.Location = new Point(3, 3);
            cmbCostume.Location = new Point(lblCostume.Right, lblCostume.Top);
            cmbCostume.Width = pnlContainer.Width - cmbCostume.Left -lblCostume.Left ;
            lbtnLoad.Location = new Point(lblCostume.Left, cmbCostume.Bottom);
            lbtnUnload.Location = new Point(lbtnLoad.Right, lbtnLoad.Top);
            lbtnNew.Location = new Point(lbtnUnload.Right, lbtnUnload.Top);
            lbtnSave.Location = new Point(lbtnNew.Right, lbtnNew.Top);
            lbtnResize.Location = new Point(lbtnLoad.Left, lbtnLoad.Bottom + 2);
            lbtnRename.Location = new Point(lbtnResize.Right, lbtnResize.Top);
        }

    }

    /// <summary>
    /// provides user with sequence of frames to edit multiple frames at a time
    /// </summary>
    public class panelAnimationFrameEditor : panelMoveable
    {
        public static panelAnimationFrameEditor instance;
        public classSpriteData cSpriteData;

        /// <summary>
        /// class used to display multiple frames in a sequence on the screen displayed on one of two sliding picturebox
        /// </summary>
        public class classcOutput
        {
            public List<Bitmap> lstAnimation_FramesBmp = new List<Bitmap>();
            public List<Bitmap> lstAnimation_FramesBmp_Shaded = new List<Bitmap>();
            public int intNumExtraFrames = 2;
            public Bitmap[] bmp = new Bitmap[2];
            public List<int> lstFrame_Indices = new List<int>();
            public List<bool> lstPic_FrameSelected_Bool = new List<bool>();
            public List<bool> lstAnimation_FrameSelected_Bool = new List<bool>();
            public int intFrame_Index_MouseOver = -1;
            public PictureBox[] pic = new PictureBox[2];

            public classcOutput()
            {
                pic[0] = new PictureBox();
                pic[1] = new PictureBox();

                ToolTip tt = formSpriteEditor_2017.instance.toolTip;
                string strPic = "display screen showing frames of the current animation.";
                tt.SetToolTip(pic[0], strPic);
                tt.SetToolTip(pic[1], strPic);
            }
        }

        /// <summary>
        /// displays frames held in SpriteEditor's clipboard memory to be re-inserted into any animation
        /// </summary>
        public class classClipBoardElement : Panel
        {
            public PictureBox pic = new PictureBox();
            public Label lblDelete = new Label();
            public Label lblInsert = new Label();
            public classAnimation_Frame cFrame;
            public Bitmap bmpFrame;

            public classClipBoardElement(ref classAnimation_Frame Frame, Bitmap bmp)
            {
                cFrame = Frame;
                bmpFrame = bmp;

                lblDelete.Text = "Delete";
                lblDelete.AutoSize = true;
                lblDelete.ForeColor = panelAnimationFrameEditor.instance.ForeColor;
                lblDelete.BackColor = panelAnimationFrameEditor.instance.BackColor;
                lblDelete.MouseEnter += lbl_MouseEnter;
                lblDelete.MouseLeave += lbl_MouseLeave;
                lblDelete.Click += LblDelete_Click;
                pic.Controls.Add(lblDelete);

                lblInsert.Text = "Insert";
                lblInsert.AutoSize = true;
                lblInsert.ForeColor = panelAnimationFrameEditor.instance.ForeColor;
                lblInsert.BackColor = panelAnimationFrameEditor.instance.BackColor;
                lblInsert.MouseEnter += lbl_MouseEnter;
                lblInsert.MouseLeave += lbl_MouseLeave;
                lblInsert.Click += LblInsert_Click;
                pic.Controls.Add(lblInsert);

                Controls.Add(pic);
                pic.Image = bmpFrame;
                pic.SizeMode = PictureBoxSizeMode.AutoSize;

                setToolTip();

                pic.Dock = DockStyle.Fill;
                pic.SizeChanged += Pic_SizeChanged;

                Dock = DockStyle.Fill;
                ContextMenu = panelAnimationFrameEditor.instance.cmnu;
            }

            private void LblInsert_Click(object sender, EventArgs e)
            {
                List<Panel> lstMyPanel = new List<Panel>();
                Panel pnlParent = (Panel)this.Parent;
                lstMyPanel.Add(pnlParent);
                panelAnimationFrameEditor.instance.Insert(ref lstMyPanel);
            }

            /// <summary>
            /// tells SpriteEditor_2017's tooltip how to handle the clipboard's pictureBoxes
            /// </summary>
            void setToolTip()
            {
                ToolTip tt = formSpriteEditor_2017.instance.toolTip;
                tt.SetToolTip(pic, "display of one of the frames currently held in the SpriteEditor's ClipBoard");
            }

            /// <summary>
            /// highlights sender Label for UI
            /// </summary>
            void lbl_MouseEnter(object sender, EventArgs e)
            {
                Label lblSender = (Label)sender;
                lblSender.ForeColor = panelAnimationFrameEditor.instance.BackColor;
                lblSender.BackColor = panelAnimationFrameEditor.instance.ForeColor;
            }

            /// <summary>
            /// returns sender Label's Costume to normal after having been highlighted by MouseEnter event
            /// </summary>
            void lbl_MouseLeave(object sender, EventArgs e)
            {
                Label lblSender = (Label)sender;
                lblSender.ForeColor = panelAnimationFrameEditor.instance.ForeColor;
                lblSender.BackColor = panelAnimationFrameEditor.instance.BackColor;

            }

            /// <summary>
            /// repositions this clipboard frame's delete button
            /// </summary>
            private void Pic_SizeChanged(object sender, EventArgs e)
            {
                lblDelete.Left = pic.Width - lblDelete.Width - 5;
                lblDelete.Top = pic.Height - lblDelete.Height - 5;
                lblInsert.Left = lblDelete.Left;
                lblInsert.Top = lblDelete.Top  - lblInsert.Height;
            }

            private void LblDelete_Click(object sender, EventArgs e)
            {
                classClipBoardElement cThis = this;
                panelAnimationFrameEditor.instance.Clipboard_Remove(ref cThis);
            }
        }

        public Panel pnlBar = new Panel();
        public Label lblLeft = new Label();
        public Label lblRight = new Label();

        public Label lblCopy_ToClipBoard = new Label();
        public Label lblInsert_Clipboard = new Label();
        public Label lblCut_ToClipBoard = new Label();
        public Label lblSelect_All = new Label();
        public Label lblUnselect_All = new Label();
        public Label lblReverseOrder = new Label();
        public Label lblDelete = new Label();
        public Label lblClear_Clipboard = new Label();

        List<classAnimation_Frame> lstFrames_Selected = new List<classAnimation_Frame>();
        List<classAnimation_Frame> lstFrames_ClipBoard = new List<classAnimation_Frame>();

        classcOutput cOutput = new classcOutput();
        public  panelScrolling_Horizontal pnlScr_H_Clipboard = new panelScrolling_Horizontal();

        public ContextMenu cmnu = new ContextMenu();

        Point ptMouse = new Point();

        public Label lblDebug = new Label();

        int intPic = 0;
        int intMaxPicHeight = 200;

        List<Label> lstLabels = new List<Label>();

        public panelAnimationFrameEditor() { Init(panelMoveable.fntStandard); }
        public panelAnimationFrameEditor(Font fnt) { Init(fnt); }
        /// <summary>
        /// initializes this panel's controls
        /// </summary>
        /// <param name="fnt"></param>
        void Init(Font fnt)
        {
            instance = this;
            Heading.Font = fnt;
            Heading.BackColor = Color.LightGray;
            Heading.ForeColor = Color.Black;


            pnlContainer.BackColor
                = pnlBar.BackColor
                = lblLeft.BackColor
                = lblRight.BackColor
                = Heading.BackColor;

            pnlContainer.ForeColor
                = pnlBar.ForeColor
                = lblLeft.ForeColor
                = lblRight.ForeColor
                = Heading.ForeColor;

            // initializes the array of classOutput which display the sequence of frames of sliding pictureboxes
            for (int intPicCounter = 0; intPicCounter < cOutput.pic.Length; intPicCounter++)
            {
                pnlContainer.Controls.Add(cOutput.pic[intPicCounter]);
                cOutput.pic[intPicCounter].MouseMove += pic_MouseMove;
                cOutput.pic[intPicCounter].MouseClick += pic_MouseClick;
                cOutput.pic[intPicCounter].MouseLeave += pic_MouseLeave;
                cOutput.pic[intPicCounter].MouseWheel += pic_MouseWheel;
            }

            lblLeft.Text = "<";
            lblLeft.Name = "lblLeft";
            lblLeft.AutoSize = false;
            lblLeft.Width = 25;
            lblLeft.TextAlign = ContentAlignment.MiddleRight;
            lblLeft.Click += LblLeft_Click;
            lblLeft.MouseWheel += Lbl_MouseWheel;
            lblLeft.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblLeft.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            pnlBar.Controls.Add(lblLeft);

            lblRight.Text = ">";
            lblRight.Name = "lblRight";
            lblRight.AutoSize = false;
            lblRight.Width = lblLeft.Width;
            lblRight.TextAlign = ContentAlignment.MiddleLeft;
            lblRight.Click += LblRight_Click;
            lblRight.MouseWheel += Lbl_MouseWheel;
            lblRight.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblRight.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            pnlBar.Controls.Add(lblRight);

            lblCopy_ToClipBoard.Text = "Copy";
            lblCopy_ToClipBoard.Name = "lblCopy_ToClipBoard";
            lblCopy_ToClipBoard.AutoSize = true;
            lblCopy_ToClipBoard.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblCopy_ToClipBoard.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblCopy_ToClipBoard.Click += lblCopy_ToClipBoard_Click;
            pnlBar.Controls.Add(lblCopy_ToClipBoard);

            lblCut_ToClipBoard.Name = "lblCut_ToClipBoard";
            lblCut_ToClipBoard.Text = "Cut";
            lblCut_ToClipBoard.AutoSize = true;
            lblCut_ToClipBoard.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblCut_ToClipBoard.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblCut_ToClipBoard.Click += lblCut_ToClipBoard_Click;
            pnlBar.Controls.Add(lblCut_ToClipBoard);

            lblDelete.Name = "lblDelete";
            lblDelete.Text = "Delete";
            lblDelete.AutoSize = true;
            lblDelete.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblDelete.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblDelete.Click += LblDelete_Click;
            pnlBar.Controls.Add(lblDelete);

            lblInsert_Clipboard.Name = "lblInsert_Clipboard";
            lblInsert_Clipboard.Text = "Insert";
            lblInsert_Clipboard.AutoSize = true;
            lblInsert_Clipboard.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblInsert_Clipboard.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblInsert_Clipboard.Click += lblInsert_Clipboard_Click;
            pnlBar.Controls.Add(lblInsert_Clipboard);

            lblClear_Clipboard.Name = "lblClear_Clipboard";
            lblClear_Clipboard.Text = "Clear";
            lblClear_Clipboard.AutoSize = true;
            lblClear_Clipboard.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblClear_Clipboard.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblClear_Clipboard.Click += lblClear_Clipboard_Click;
            pnlBar.Controls.Add(lblClear_Clipboard);

            lblSelect_All.Name = "lblSelect_All";
            lblSelect_All.Text = "Select All";
            lblSelect_All.AutoSize = true;
            lblSelect_All.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblSelect_All.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblSelect_All.Click += lblSelect_All_Click;
            pnlBar.Controls.Add(lblSelect_All);

            lblUnselect_All.Name = "lblUnselect_All";
            lblUnselect_All.Text = "Unselect All";
            lblUnselect_All.AutoSize = true;
            lblUnselect_All.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblUnselect_All.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblUnselect_All.Click += lblUnselect_All_Click;
            pnlBar.Controls.Add(lblUnselect_All);
                        
            lblReverseOrder.Name = "lblReverseOrder";
            lblReverseOrder.Text = "ReverseOrder All";
            lblReverseOrder.AutoSize = true;
            lblReverseOrder.MouseEnter += formSpriteEditor_2017.instance.lbl_MouseEnter;
            lblReverseOrder.MouseLeave += formSpriteEditor_2017.instance.lbl_MouseLeave;
            lblReverseOrder.Click += lblReverseOrder_Click;
            pnlBar.Controls.Add(lblReverseOrder);

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

            pnlContainer.Controls.Add(lblDebug);
            lblDebug.Name = "lblDebug";
            lblDebug.AutoSize = true;
            lblDebug.Font = new Font("courier", 12, FontStyle.Regular);
            lblDebug.ForeColor = Color.Black;
            lblDebug.Click += LblDebug_Click;

            lstLabels = new List<Label>();
            lstLabels.Add(lblCopy_ToClipBoard);
            lstLabels.Add(lblCut_ToClipBoard);
            lstLabels.Add(lblInsert_Clipboard);
            lstLabels.Add(lblDelete);
            lstLabels.Add(lblClear_Clipboard);
            lstLabels.Add(lblSelect_All);
            lstLabels.Add(lblUnselect_All);
            lstLabels.Add(lblReverseOrder);
            Size szLabels_Min = new Size();
            // sizes and positions all the label-button controls on this panel
            for (int intLabelCounter = 0; intLabelCounter < lstLabels.Count; intLabelCounter++)
            {
                Label lbl = lstLabels[intLabelCounter];
                lbl.TextAlign = ContentAlignment.MiddleCenter;
                if (lbl.Width > szLabels_Min.Width) szLabels_Min.Width = lbl.Width;
                if (lbl.Height > szLabels_Min.Height) szLabels_Min.Height = lbl.Height;
                lbl.AutoSize = false;
            }

            for (int intLabelCounter = 0; intLabelCounter < lstLabels.Count; intLabelCounter++)
            {
                Label lbl = lstLabels[intLabelCounter];
                lbl.Size = szLabels_Min;
            }

            pnlContainer.Controls.Add(pnlScr_H_Clipboard);

            MenuItem mnuCut = new MenuItem("Cut", lblCut_ToClipBoard_Click);
            MenuItem mnuCopy = new MenuItem("Copy", lblCopy_ToClipBoard_Click);
            MenuItem mnuInsert = new MenuItem("Insert", lblInsert_Clipboard_Click);
            MenuItem mnuDelete = new MenuItem("Delete", LblDelete_Click);
            MenuItem mnuClear = new MenuItem("Clear", lblClear_Clipboard_Click);
            MenuItem mnuSelectAll = new MenuItem("Select All", lblSelect_All_Click);
            MenuItem mnuUnselectAll = new MenuItem("Unselect All", lblUnselect_All_Click);
            MenuItem mnuReverseOrder = new MenuItem("Reverse Order", lblReverseOrder_Click);

            cmnu.MenuItems.Add(mnuCut);
            cmnu.MenuItems.Add(mnuCopy);
            cmnu.MenuItems.Add(mnuInsert);
            cmnu.MenuItems.Add(mnuDelete);
            cmnu.MenuItems.Add(mnuClear);
            cmnu.MenuItems.Add(mnuSelectAll);
            cmnu.MenuItems.Add(mnuUnselectAll);
            cmnu.MenuItems.Add(mnuReverseOrder);

            // pnlScr_H_Clipboard is a scrolling horizontal panel which contains all the clipboard frames
            pnlScr_H_Clipboard.Name = "pnlScr_H_Clipboard";
            pnlScr_H_Clipboard.ContextMenu = cmnu;
            cOutput.pic[0].ContextMenu = cmnu;
            cOutput.pic[1].ContextMenu = cmnu;

            Text = "Animation Frame Editor";

            setToolTip();
            init_Format();
            SizeChanged += panelAnimationFrameEditor_SizeChanged;
            LocationChanged += panelAnimationFrameEditor_LocationChanged;
            Disposed += panelAnimationFrameEditor_Disposed;
        }

        public void init_Format()
        {  // sets format of panel according to data read in Format_Load() earlier
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].location_Y);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolIgnoreChanges = false;
        }

        /// <summary>
        /// binds the panel's controls to formSpriteEditor_2017's tooltip
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            // panelAnimationFrameEditor
            tt.SetToolTip(pnlBar, "control bar holds all editing controls");
            tt.SetToolTip(lblLeft, "shifts to previous frame");
            tt.SetToolTip(lblRight, "shifts to next frame");
            tt.SetToolTip(lblCopy_ToClipBoard, "makes a copy of selected frames and adds them to the AnimationFrameEditor's clipboard");
            tt.SetToolTip(lblInsert_Clipboard, "inserts all clipboard frames into animation after the first selected frame in animation(0th frame if none selected).");
            tt.SetToolTip(lblCut_ToClipBoard, "removes selected frames from animation and copies them onto the AnimationFrameEditor's clipboard.");
            tt.SetToolTip(lblDelete, "deletes all selected frames from the animation.");
            tt.SetToolTip(lblClear_Clipboard, "deletes all frames from the clipboard");
            tt.SetToolTip(lblSelect_All, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblUnselect_All, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblReverseOrder, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(pnlScr_H_Clipboard, "the clipboard is where frames are stored when being edited to/from the animation");
            tt.SetToolTip(lblDebug, "invaluable tool used by the writer to get this thing to scroll properly.");
        }

        /// <summary>
        /// reacts to mousewheel event to scroll the storyboard forward along the animation's list of frames
        /// </summary>
        private void pic_MouseWheel(object sender, MouseEventArgs e)
        {
            Lbl_MouseWheel(sender, e);
        }

        /// <summary>
        /// unhighlights the frame that was under the mouse cursor
        /// </summary>
        private void pic_MouseLeave(object sender, EventArgs e)
        {
            cOutput.intFrame_Index_MouseOver = -1;
            Highlight_SelectedFrames();
        }

        /// <summary>
        /// selects/unselects this frame of the animation in the storyboard sequence of frames
        /// </summary>
        private void pic_MouseClick(object sender, MouseEventArgs e)
        {
            if (cOutput.intFrame_Index_MouseOver < 0) return;

            cOutput.lstPic_FrameSelected_Bool[cOutput.intFrame_Index_MouseOver] = !cOutput.lstPic_FrameSelected_Bool[cOutput.intFrame_Index_MouseOver];

            int intFrameSelected = cOutput.lstFrame_Indices[cOutput.intFrame_Index_MouseOver];
            cOutput.lstAnimation_FrameSelected_Bool[intFrameSelected] = !cOutput.lstAnimation_FrameSelected_Bool[intFrameSelected];

            Highlight_SelectedFrames();
        }


        /// <summary>
        /// highlights the frame under the mouse cursor
        /// </summary>
        private void pic_MouseMove(object sender, MouseEventArgs e)
        {
            ptMouse.X = e.X;
            ptMouse.Y = e.Y;
            int intFrame_MouseOver = (int)Math.Floor((double)ptMouse.X / (double)szFrame.Width);
            if (intFrame_MouseOver != cOutput.intFrame_Index_MouseOver)
            {
                cOutput.intFrame_Index_MouseOver = intFrame_MouseOver;
                Highlight_SelectedFrames();
            }
        }

        void lblSelect_All_Click(object sender, EventArgs e)
        {
            for (int intCounter = 0; intCounter < cOutput.lstAnimation_FrameSelected_Bool.Count; intCounter++)
            {
                cOutput.lstAnimation_FrameSelected_Bool[intCounter] = true;
            }

            for (int intCounter = 0; intCounter < cOutput.lstPic_FrameSelected_Bool.Count; intCounter++)
            {
                cOutput.lstPic_FrameSelected_Bool[intCounter] = true;
            }

            Highlight_SelectedFrames();
        }
        void lblUnselect_All_Click(object sender, EventArgs e)
        {

            for (int intCounter = 0; intCounter < cOutput.lstAnimation_FrameSelected_Bool.Count; intCounter++)
            {
                cOutput.lstAnimation_FrameSelected_Bool[intCounter] = false;
            }

            for (int intCounter = 0; intCounter < cOutput.lstPic_FrameSelected_Bool.Count; intCounter++)
            {
                cOutput.lstPic_FrameSelected_Bool[intCounter] = false;
            }

            Highlight_SelectedFrames();
        }

        void lblReverseOrder_Click(object sender, EventArgs e)
        {
            List<Panel> lstPanelReversed = new List<Panel>();
            for (int intPanelCounter = 0; intPanelCounter < pnlScr_H_Clipboard.lstPanels.Count; intPanelCounter++)
            {
                lstPanelReversed.Insert(0, pnlScr_H_Clipboard.lstPanels[intPanelCounter]);
            }
            pnlScr_H_Clipboard.lstPanels = lstPanelReversed;
            pnlScr_H_Clipboard.PositionPanels();
            Highlight_SelectedFrames();
        }


        /// <summary>
        /// clears the clipboard of all the frames that are currently held there
        /// </summary>
        private void lblClear_Clipboard_Click(object sender, EventArgs e)
        {
            pnlScr_H_Clipboard.clear();
        }

        /// <summary>
        /// copies the frames currently selected in the storyboard and places the copies onto the clipboard
        /// </summary>
        private void lblCopy_ToClipBoard_Click(object sender, EventArgs e)
        {
            for (int intCounter = 0; intCounter < cOutput.lstAnimation_FrameSelected_Bool.Count; intCounter++)
            {
                if (cOutput.lstAnimation_FrameSelected_Bool[intCounter])
                {
                    classAnimation_Frame cFrameCopy = cSpriteData.cAnimationData.cAnimation.lstFrames[intCounter].Copy();
                    Bitmap bmpCopy = (Bitmap)new Bitmap(cOutput.lstAnimation_FramesBmp[intCounter]);
                    panelAnimationFrameEditor.classClipBoardElement cClipBoardElement = new classClipBoardElement(ref cFrameCopy, bmpCopy);

                    Panel pnlClipBoardContainer = new Panel();

                    pnlClipBoardContainer.Controls.Add(cClipBoardElement);
                    pnlClipBoardContainer.Size = szFrame;
                    pnlScr_H_Clipboard.AddPanel(ref pnlClipBoardContainer);
                }
            }
        }

        /// <summary>
        /// removes the frames currently selected from the storyboard and places them onto the clipboard
        /// </summary>
        private void lblCut_ToClipBoard_Click(object sender, EventArgs e)
        {
            if (cSpriteData.cAnimationData.cAnimation.lstFrames.Count < 2)
            {
                MessageBox.Show("You cannot delete all the frames of an animation.");
                return;
            }

            for (int intCounter = cOutput.lstAnimation_FrameSelected_Bool.Count - 1; intCounter >= 0; intCounter--)
            {
                if (cOutput.lstAnimation_FrameSelected_Bool[intCounter])
                {
                    classAnimation_Frame cFrame = cSpriteData.cAnimationData.cAnimation.lstFrames[intCounter];
                    Bitmap bmp = getFrameImage(intCounter, false);

                    classClipBoardElement cClipBoardItem = new classClipBoardElement(ref cFrame, bmp);

                    Panel pnlClipBoardContainer = new Panel();
                    pnlClipBoardContainer.Size = szFrame;
                    pnlClipBoardContainer.Controls.Add(cClipBoardItem);
                    pnlScr_H_Clipboard.AddPanel(ref pnlClipBoardContainer);

                    cSpriteData.cAnimationData.cAnimation.Frame_Sub(intCounter);
                }
            }
            SetAnimationFrameEditor();
        }

        /// <summary>
        /// deletes all currently selected frames from this animation
        /// </summary>
        private void LblDelete_Click(object sender, EventArgs e)
        {
            if (cSpriteData.cAnimationData.cAnimation.lstFrames.Count < 2)
            {
                MessageBox.Show("You cannot delete all the frames of an animation.");
                return;
            }


            for (int intCounter = cOutput.lstAnimation_FrameSelected_Bool.Count - 1; intCounter >= 0; intCounter--)
            {
                if (cOutput.lstAnimation_FrameSelected_Bool[intCounter] && cSpriteData.cAnimationData.cAnimation.lstFrames.Count >0)
                {
                    if (cSpriteData.cAnimationData.cAnimation.lstFrames.Count >1)
                    cSpriteData.cAnimationData.cAnimation.Frame_Sub(intCounter);
                }
            }
            SetAnimationFrameEditor();
            formSpriteEditor_2017.instance.nudFrameCounter_Reset();
        }

        /// <summary>
        /// inserts all the frames currently in the clipboard into the animation immediately after the first selected frame counting from zero, or after zero if none selected
        /// </summary>
        private void lblInsert_Clipboard_Click(object sender, EventArgs e)
        {
            List<Panel> lstPanels = pnlScr_H_Clipboard.lstPanels;
            Insert(ref lstPanels);
        }

        /// <summary>
        /// inserts the specified list of frames into the animation immediately after the first selected frame, or after the zero-th frame if none selected
        /// </summary>
        /// <param name="lstClipboard_Panels">list of animation frames to be inserted into the currently selected animation</param>
        public void Insert(ref List<Panel> lstClipboard_Panels)
        { 
            int intInsertAfterFrame_Index = cOutput.intFrame_Index_MouseOver;
            if (intInsertAfterFrame_Index < 0)
            {
                for (int intCounter = 0; intCounter < cOutput.lstAnimation_FrameSelected_Bool.Count; intCounter++)
                {
                    if (cOutput.lstAnimation_FrameSelected_Bool[intCounter])
                    {
                        intInsertAfterFrame_Index = intCounter;
                        break;
                    }
                }
            }
            if (intInsertAfterFrame_Index < 0) intInsertAfterFrame_Index = 0;

            for (int intCounter = 0; intCounter < lstClipboard_Panels.Count; intCounter++)
            {
                Panel pnlClipBoardContainer = lstClipboard_Panels[intCounter];
                classClipBoardElement cClipboardElement = (classClipBoardElement)pnlClipBoardContainer.Controls[0];

                classAnimation_Frame cFrame = cClipboardElement.cFrame.Copy();
                cSpriteData.cAnimationData.cAnimation.Frame_Add(intInsertAfterFrame_Index + intCounter, ref cFrame, false);
            }

            SetAnimationFrameEditor();
            formSpriteEditor_2017.instance.nudFrameCounter_Reset();
        }

        /// <summary>
        /// displays frames information necessary during development for the sake of debugging the scrolling feature of the storyboard
        /// </summary>
        private void LblDebug_Click(object sender, EventArgs e)
        {
            displayHelp();
        }

        /// <summary>
        /// removes specified frame from the clipboard
        /// </summary>
        /// <param name="cClipBoardElement">container class of the frame to be removed</param>
        public void Clipboard_Remove(ref classClipBoardElement cClipBoardElement)
        {
            Panel pnlParent = (Panel)cClipBoardElement.Parent;
            pnlScr_H_Clipboard.SubPanel(ref pnlParent);
            classAnimation_Frame cFrameToRemove = cClipBoardElement.cFrame;
            lstFrames_ClipBoard.Remove(cFrameToRemove);
            pnlScr_H_Clipboard.PositionPanels();

        }

        /// <summary>
        /// ensures the panel's current expansion/collapse settings are recorded before the SpriteEditor_2017 IDE is disposed
        /// </summary>
        private void panelAnimationFrameEditor_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].Collapsed = Collapsed;
        }

        /// <summary>
        /// records the panel's location to be saved into the format.txt file
        /// </summary>
        private void panelAnimationFrameEditor_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolInit = true;
            }
        }

        /// <summary>
        /// records the panel's size for later formatting during load time
        /// </summary>
        private void panelAnimationFrameEditor_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolIgnoreChanges
                     && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AnimationFrameEditor].Collapsed = Collapsed;


            setHeadingText();

            placeObjects();
        }

        /// <summary>
        /// sets the text displayed in the panel's heading
        /// </summary>
        void setHeadingText()
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            if (Collapsed)
                Heading.Text = "Animation Frame Editor";
            else
                Heading.Text = "Animation : " + cSpriteData.cAnimationData.cAnimation.Name;
        }

        /// <summary>
        /// advances the storyboard one frame
        /// </summary>
        private void LblRight_Click(object sender, EventArgs e) { Shift_Frame_Next(); }

        /// <summary>
        /// regresses the storyboard one frame
        /// </summary>
        private void LblLeft_Click(object sender, EventArgs e) { Shift_Frame_Previous(); }

        /// <summary>
        /// handles Label mouse wheel events to scroll the storyboard forwards/backwards
        /// </summary>
        private void Lbl_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
                Shift_Frame_Next();
            else
                Shift_Frame_Previous();
        }

        /// <summary>
        /// points to the currently displayed storyboard panel
        /// </summary>
        int Current { get { return intPic; } }
        /// <summary>
        /// points to the previous/next storyboard panel
        /// </summary>
        int Next { get { return (intPic + 1) % 2; } }

        /// <summary>
        /// changes the storyboard panel pointer to point to the next storyboard panel
        /// </summary>
        void cyclePic()
        {
            intPic = (intPic + 1) % 2;
            cOutput.pic[Current].BringToFront();
        }

        /// <summary>
        /// slides the storyboard left one frame until it reaches the end of its content then loads the next storyboard panel to replace it seamlessly
        /// </summary>
        public void Shift_Frame_Next()
        {
            intFrameCurrent = (intFrameCurrent + 1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count;
            formSpriteEditor_2017.instance.Message("Shift Frame Next:" + intFrameCurrent.ToString());

            if (cOutput.pic[Current].Right - szFrame.Width >= pnlContainer.Width)
            {
                cOutput.pic[Current].Left -= szFrame.Width;
                Highlight_SelectedFrames();
            }
            else
            {
                int intNumFramesToCopy = intFramesPerPic - cOutput.intNumExtraFrames - 1;
                Rectangle recSource_Copy = new Rectangle(new Point(szFrame.Width * (cOutput.intNumExtraFrames + 1), 0), new Size(szFrame.Width * intNumFramesToCopy, szFrame.Height));
                Rectangle recDestination_Copy = new Rectangle(classGraphics.ptZero, recSource_Copy.Size);
                Bitmap bmp = new Bitmap(cOutput.pic[0].Width, cOutput.pic[1].Height);

                int intStartFrame = cOutput.lstFrame_Indices[cOutput.lstFrame_Indices.Count - 1] + 1;
                // remove the booleans that are scrolling off the screen
                for (int intCounter = 0; intCounter < cOutput.intNumExtraFrames + 1; intCounter++)
                    cOutput.lstPic_FrameSelected_Bool.Remove(cOutput.lstPic_FrameSelected_Bool[0]);

                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.DrawImage(cOutput.bmp[Current], recDestination_Copy, recSource_Copy, GraphicsUnit.Pixel);

                    Rectangle recSource = new Rectangle(classGraphics.ptZero, szFrame);
                    for (int intCounter = 0; intCounter < cOutput.intNumExtraFrames + 1; intCounter++)
                    {
                        cOutput.lstFrame_Indices.Remove(cOutput.lstFrame_Indices[0]);

                        int intFrame = (intCounter + intStartFrame) % cOutput.lstAnimation_FramesBmp.Count;
                        cOutput.lstFrame_Indices.Add(intFrame);
                        cOutput.lstPic_FrameSelected_Bool.Add(cOutput.lstAnimation_FrameSelected_Bool[intFrame]);

                        Rectangle recDestination = new Rectangle(new Point(recDestination_Copy.Right + szFrame.Width * intCounter, 0), szFrame);

                        g.DrawImage(cOutput.lstAnimation_FramesBmp[intFrame], recDestination, recSource, GraphicsUnit.Pixel);
                    }
                }

                cOutput.bmp[Next] = bmp;
                cOutput.pic[Next].Image = bmp;
                cOutput.pic[Next].Left = 0;

                cyclePic();



                Highlight_SelectedFrames();

            }
            displayHelp();
        }

        /// <summary>
        /// slides the storyboard right one frame until it reaches the end of its content then loads the 'previous' storyboard panel to replace it seamlessly
        /// </summary>
        public void Shift_Frame_Previous()
        {
            intFrameCurrent = (intFrameCurrent + cSpriteData.cAnimationData.cAnimation.lstFrames.Count - 1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count;

            formSpriteEditor_2017.instance.Message("Shift Frame Previous:" + intFrameCurrent.ToString());
            int intIndexCurrentInList = cOutput.lstFrame_Indices.IndexOf(intFrameCurrent);
            if (cOutput.pic[Current].Left + szFrame.Width <= 0)
            {
                cOutput.pic[Current].Left += szFrame.Width;
                Highlight_SelectedFrames();
            }
            else
            {
                int intNumFramesToCopy = intFramesPerPic - cOutput.intNumExtraFrames - 1;
                Rectangle recSource_Copy = new Rectangle(classGraphics.ptZero, new Size(szFrame.Width * intNumFramesToCopy, szFrame.Height));
                Rectangle recDestination_Copy = new Rectangle(new Point(szFrame.Width * (cOutput.intNumExtraFrames + 1), 0), recSource_Copy.Size);
                Bitmap bmp = new Bitmap(cOutput.pic[0].Width, cOutput.pic[1].Height);

                int intStartFrame = cOutput.lstFrame_Indices[0] - 1 - cOutput.intNumExtraFrames;

                List<int> lstTemp_Int = new List<int>();
                for (int intCopyCounter = 0; intCopyCounter < cOutput.lstFrame_Indices.Count - cOutput.intNumExtraFrames - 1; intCopyCounter++)
                    lstTemp_Int.Add(cOutput.lstFrame_Indices[intCopyCounter]);

                List<bool> lstTemp_Bool = new List<bool>();
                for (int intCopyCounter = 0; intCopyCounter < cOutput.lstPic_FrameSelected_Bool.Count - cOutput.intNumExtraFrames - 1; intCopyCounter++)
                    lstTemp_Bool.Add(cOutput.lstPic_FrameSelected_Bool[intCopyCounter]);


                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.DrawImage(cOutput.bmp[Current], recDestination_Copy, recSource_Copy, GraphicsUnit.Pixel);

                    Rectangle recSource = new Rectangle(classGraphics.ptZero, szFrame);

                    for (int intCounter = 0; intCounter < cOutput.intNumExtraFrames + 1; intCounter++)
                    {
                        int intFrame = (intCounter + intStartFrame + cOutput.lstAnimation_FramesBmp.Count) % cOutput.lstAnimation_FramesBmp.Count;

                        lstTemp_Int.Insert(intCounter, intFrame);
                        lstTemp_Bool.Insert(intCounter, cOutput.lstAnimation_FrameSelected_Bool[intFrame]);

                        Rectangle recDestination = new Rectangle(new Point(szFrame.Width * intCounter, 0), szFrame);

                        g.DrawImage(cOutput.lstAnimation_FramesBmp[intFrame], recDestination, recSource, GraphicsUnit.Pixel);

                    }
                }

                cOutput.lstFrame_Indices = lstTemp_Int;
                cOutput.lstPic_FrameSelected_Bool = lstTemp_Bool;

                cOutput.bmp[Next] = bmp;
                cOutput.pic[Next].Image = bmp;
                cOutput.pic[Next].Left = -szFrame.Width * (cOutput.intNumExtraFrames);

                cyclePic();

                Highlight_SelectedFrames();

            }
            displayHelp();
        }

        /// <summary>
        /// redraws currently visible storyboard bitmap to highlight those frames that are selected
        /// </summary>
        void Highlight_SelectedFrames()
        {
            Bitmap bmpHighlight = (Bitmap)new Bitmap(cOutput.bmp[Current]);

            using (Graphics g = Graphics.FromImage(bmpHighlight))
            {
                Rectangle recSource = new Rectangle(classGraphics.ptZero, szFrame);
                bool bolMouseOverDone = false;
                for (int intCounter = 0; intCounter < cOutput.lstPic_FrameSelected_Bool.Count; intCounter++)
                {
                    if (cOutput.lstPic_FrameSelected_Bool[intCounter])
                    {
                        if (cOutput.intFrame_Index_MouseOver == intCounter) bolMouseOverDone = true;
                        Rectangle recDestination = new Rectangle(new Point(szFrame.Width * intCounter, 0), szFrame);
                        g.DrawImage(cOutput.lstAnimation_FramesBmp_Shaded[cOutput.lstFrame_Indices[intCounter]], recDestination, recSource, GraphicsUnit.Pixel);
                    }
                }

                if (!bolMouseOverDone && cOutput.intFrame_Index_MouseOver >= 0)
                {
                    Rectangle recDestination = new Rectangle(new Point(szFrame.Width * cOutput.intFrame_Index_MouseOver, 0), szFrame);
                    Bitmap bmp = cOutput.lstAnimation_FramesBmp_Shaded[cOutput.lstFrame_Indices[cOutput.intFrame_Index_MouseOver]];
                    //bmp.Save("c:\\debug\\bmp.bmp");
                    g.DrawImage(bmp, recDestination, recSource, GraphicsUnit.Pixel);
                }

            }
           
            cOutput.pic[Current].Image = bmpHighlight;
            cOutput.pic[Current].Refresh();
        }

        /// <summary>
        /// positions controls onto this panel
        /// </summary>
        void placeObjects()
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            pnlBar.Left = 0;
            pnlBar.Top = 0;
            pnlBar.Width = pnlContainer.Width;
            pnlBar.Height = 25;

            lblLeft.Top
                = lblRight.Top
                = lblCopy_ToClipBoard.Top
                = lblCut_ToClipBoard.Top
                = lblInsert_Clipboard.Top
                = lblDelete.Top
                = lblClear_Clipboard.Top
                = lblSelect_All.Top 
                = lblUnselect_All.Top
                = (pnlBar.Height - lblLeft.Height) / 2;

            for (int intLabelCounter = 0; intLabelCounter < lstLabels.Count; intLabelCounter++)
            {
                Label lbl = lstLabels[intLabelCounter];
                lbl.Left = intLabelCounter * lbl.Width;
            }

            lblLeft.Left = lstLabels[lstLabels.Count - 1].Right + 5;
            lblRight.Left = lblLeft.Right;


            for (int intPicCounter = 0; intPicCounter < cOutput.pic.Length; intPicCounter++)
            {
                PictureBox pic = cOutput.pic[intPicCounter];
                pic.Top = pnlBar.Bottom;
                pic.Height = (pnlContainer.Height - pic.Top) / 2;
                if (pic.Height > intMaxPicHeight) pic.Height = intMaxPicHeight;
                pic.Width = pnlContainer.Width * 2;
            }
            cOutput.pic[Current].BringToFront();

            pnlScr_H_Clipboard.Left = 0;
            pnlScr_H_Clipboard.Top = cOutput.pic[0].Bottom;
            pnlScr_H_Clipboard.Width = pnlContainer.Width;
            pnlScr_H_Clipboard.Height = cOutput.pic[0].Height + pnlScr_H_Clipboard.Hsb.Height;


            lblDebug.Top = pnlScr_H_Clipboard.Bottom;
            lblDebug.Left = 2;
            lblDebug.AutoSize = true;

            SetAnimationFrameEditor();
        }

        /// <summary>
        /// resets the contents of the panelAnimationFrameEditor to reflect the currently selected Sprite and Animation
        /// </summary>
        public void SetAnimationFrameEditor()
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            intFrameCurrent = cSpriteData.cAnimationData.intFrameIndex;

            setPicFrames();

            setIndices(cSpriteData.cAnimationData.intFrameIndex);

            cOutput.lstAnimation_FrameSelected_Bool = new List<bool>();
            for (int intCounter = 0; intCounter < cSpriteData.cAnimationData.cAnimation.lstFrames.Count; intCounter++)
                cOutput.lstAnimation_FrameSelected_Bool.Add(false);

            cOutput.lstPic_FrameSelected_Bool = new List<bool>();
            for (int intCounter = 0; intCounter < cOutput.lstFrame_Indices.Count; intCounter++)
                cOutput.lstPic_FrameSelected_Bool.Add(false);

            /// draw original Bitmap
            Bitmap bmp = new Bitmap(cOutput.pic[0].Width, cOutput.pic[0].Height);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                // color background
                g.FillRectangle(Brushes.White, new Rectangle(classGraphics.ptZero, cOutput.pic[0].Size));

                // draw all frames onto screen
                Rectangle recSource = new Rectangle(classGraphics.ptZero, szFrame);
                for (int intCounter = 0; intCounter < cOutput.lstFrame_Indices.Count; intCounter++)
                {
                    Rectangle recDestination = new Rectangle(new Point(szFrame.Width * intCounter, 0), szFrame);
                    g.DrawImage(cOutput.lstAnimation_FramesBmp[cOutput.lstFrame_Indices[intCounter]], recDestination, recSource, GraphicsUnit.Pixel);
                }
            }
            cOutput.bmp[Current] = bmp;
            cOutput.pic[Current].Image = cOutput.bmp[Current];
            cOutput.pic[Current].Left = 0;
            displayHelp();
            setHeadingText();
        }

        /// <summary>
        /// records the indices of the frames are currently drawn onto the sliding storyboard
        /// </summary>
        /// <param name="intStart"></param>
        void setIndices(int intStart)
        {
            cOutput.lstFrame_Indices.Clear();
            for (int intCounter = 0; intCounter < intFramesPerPic; intCounter++)
            {
                cOutput.lstFrame_Indices.Add((intStart + intCounter) % cOutput.lstAnimation_FramesBmp.Count);
            }
        }

        Size szFrame = new Size();
        Font fntFrameIndex = new Font("courier", 12, FontStyle.Regular);
        int intFramesPerPic, intFramesPerScreen;

        int _intFrameCurrent = 0;
        /// <summary>
        /// centers storyboard around the intFrameCurrent
        /// </summary>
        int intFrameCurrent
        {
            get { return _intFrameCurrent; }
            set
            {
                _intFrameCurrent = value;
                displayHelp();
            }
        }

        /// <summary>
        /// displays information about the frames and their indices to animation scrolling storyboard
        /// </summary>
        void displayHelp()
        {
            try
            {
                string strText = "";

                int intFramesToTheLeft = ((int)Math.Ceiling((double)cOutput.pic[Current].Left / (double)szFrame.Width));
                strText += "\r\nframes Left  =" + Math.Abs(intFramesToTheLeft).ToString();

                int intFramesToTheRight = ((int)Math.Floor((double)(cOutput.pic[Current].Right - pnlContainer.Width) / (double)szFrame.Width));
                if (intFramesToTheRight <= 0) intFramesToTheRight = 0;
                strText += "\r\nframes Right =" + Math.Abs(intFramesToTheRight).ToString();

                strText += "\r\n Current : ";
                List<int> lstCurrent = cOutput.lstFrame_Indices;
                for (int intCounter = 0; intCounter < lstCurrent.Count; intCounter++)
                    strText += (intCounter == 0 ? "" : ", ") + lstCurrent[intCounter].ToString("00");

                strText += "\r\nnum Per Screen    = " + intFramesPerScreen.ToString();
                strText += "\r\nnum per Pic       = " + intFramesPerPic.ToString();
                strText += "\r\nnum per animation = " + cOutput.lstAnimation_FramesBmp.Count.ToString();


                lblDebug.Text = strText;
            }
            catch (Exception err)
            {
                System.Diagnostics.Debug.Print(err.Message);
            }
        }

        /// <summary>
        /// number of frames drawn onto the sliding pictureboxes that are not visible to the user until the picturebox is slid over to reveal them
        /// </summary>
        const int conNumExtraFrames_Default = 2;
        double dblDrawFrameStripSize = 1.0;
        List<Bitmap> lstBmpSource = new List<Bitmap>();
        /// <summary>
        /// measures all Animation source images, resizes and copies them to frames for panelAnimationFrameEditor to use
        /// </summary>
        void setPicFrames()
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            classAnimation cAnimation = cSpriteData.cAnimationData.cAnimation;
            classSpriteData.classAnimationData cAnimationData = cSpriteData.cAnimationData.Copy();
            Size szPicFrame_Source = new Size();

            cSpriteData.cAnimationData.dblDrawSizeFactor = 1.0;
            cOutput.lstAnimation_FramesBmp.Clear();
            cOutput.lstAnimation_FramesBmp_Shaded.Clear();

            lstBmpSource.Clear();
            for (cSpriteData.cAnimationData.intFrameIndex = 0; cSpriteData.cAnimationData.intFrameIndex < cAnimation.lstFrames.Count; cSpriteData.cAnimationData.intFrameIndex++)
            {
                Bitmap bmpFrame =new Bitmap( cSpriteData.cAnimationData.cSprite.draw_Animation_Frame(ref cSpriteData));
                lstBmpSource.Add( bmpFrame);

                if (bmpFrame.Width > szPicFrame_Source.Width) szPicFrame_Source.Width = bmpFrame.Width;
                if (bmpFrame.Height > szPicFrame_Source.Height) szPicFrame_Source.Height = bmpFrame.Height;
            }
            cSpriteData.cAnimationData = cAnimationData.Copy();
            dblDrawFrameStripSize = (double)cOutput.pic[0].Height / (double)szPicFrame_Source.Height;

            szFrame = new Size((int)(szPicFrame_Source.Width * dblDrawFrameStripSize), (int)(szPicFrame_Source.Height * dblDrawFrameStripSize));

            cOutput.intNumExtraFrames = conNumExtraFrames_Default;
            intFramesPerPic = (int)Math.Ceiling(((double)pnlContainer.Width)
                                                    /
                                                    szFrame.Width) + cOutput.intNumExtraFrames;


            if (intFramesPerPic % 2 == 1)
            {
                intFramesPerPic++;
                cOutput.intNumExtraFrames = 3;
            }
            cOutput.pic[0].Width
                  = cOutput.pic[1].Width
                  = szFrame.Width * intFramesPerPic;


            for (int intFrameCounter = 0; intFrameCounter < cAnimation.lstFrames.Count; intFrameCounter++)
            {
                Bitmap bmpFrameImage = getFrameImage(intFrameCounter, true);
                cOutput.lstAnimation_FramesBmp.Add(bmpFrameImage);

                Bitmap bmpFrameImage_Shaded = new Bitmap(szFrame.Width, szFrame.Height);
                using (Graphics g = Graphics.FromImage(bmpFrameImage_Shaded))
                {
                    Bitmap bmpFrameImage_Copy = (Bitmap)new Bitmap(bmpFrameImage);
                    bmpFrameImage_Copy.MakeTransparent(bmpFrameImage.GetPixel(0, 0));

                    Rectangle recSource = new Rectangle(classGraphics.ptZero, szFrame);
                    Rectangle recDestination = new Rectangle(classGraphics.ptZero, szFrame);
                    //                  bmpFrameImage_Copy.Save("c:\\debug\\bmp.bmp");
                    g.FillRectangle(Brushes.LightGray, recDestination);


                    g.DrawImage(bmpFrameImage_Copy, classGraphics.ptZero);

                    // bmpFrameImage_Shaded.Save("c:\\debug\\bmp_shaded" + intFrameCounter.ToString("00") + ".bmp");
                }
                cOutput.lstAnimation_FramesBmp_Shaded.Add(bmpFrameImage_Shaded);
            }

            intFramesPerScreen = (int)Math.Ceiling((double)pnlContainer.Width / (double)szFrame.Width);
            int intShiftToCenterHighlight = (int)(Math.Ceiling((double)intFramesPerScreen / 2.0)) - 1;
        }

        /// <summary>
        /// returns the specified frame image identified by index
        /// </summary>
        /// <param name="intFrameIndex">index of the frame to be retrieved</param>
        /// <param name="bolDrawFrameIndex">when set the frame's index number is drawn onto the frame's image</param>
        /// <returns>the image of the specified frame</returns>
        Bitmap getFrameImage(int intFrameIndex, bool bolDrawFrameIndex)
        {
            Bitmap bmpRetVal = new Bitmap(szFrame.Width, szFrame.Height);
            using (Graphics g = Graphics.FromImage(bmpRetVal))
            {
                try
                {
                    g.FillRectangle(Brushes.White, new Rectangle(classGraphics.ptZero, szFrame));

                    Size szSource = lstBmpSource[intFrameIndex].Size;
                    Rectangle recSource = new Rectangle(classGraphics.ptZero, szSource);
                    Rectangle recDestination = new Rectangle(classGraphics.ptZero,
                                                             new Size((int)(szSource.Width * dblDrawFrameStripSize),
                                                                      (int)(szSource.Height * dblDrawFrameStripSize)));
                    g.DrawImage(lstBmpSource[intFrameIndex], recDestination, recSource, GraphicsUnit.Pixel);

                    g.DrawRectangle(Pens.Black, new Rectangle(Math3.classGraphics.ptOne, new Size(szFrame.Width - 2, szFrame.Height - 2)));

                    if (bolDrawFrameIndex)
                    {
                        string strFrame = intFrameIndex.ToString();
                        g.DrawString(strFrame, fntFrameIndex, Brushes.Black, classGraphics.ptFour);
                        g.DrawString(strFrame, fntFrameIndex, Brushes.Yellow, classGraphics.ptTwo);
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error in panelAnimationFrameEditor.getFrameImage() :" + e.Message);
                }
            }
            return bmpRetVal;
        }
    }

   /// <summary>
   /// provides an interface to insert multiple frames between two existing frame to generate a smooth transition from start to finish
   /// </summary>
    public class panelAutoInsertIntermediaryFrames : panelMoveable
    {
        formSpriteEditor_2017 frmSpriteEditor = null;
        classSpriteData cSpriteData;
        classAnimation_Frame cFrame_Start;
        classAnimation_Frame cFrame_End;
        classAnimation cAnimation;
        
        public PictureBox picStart = new PictureBox();
        public Label lblPicStart = new Label();

        public PictureBox picEnd = new PictureBox();
        public Label lblPicEnd = new Label();

        public Label lblNumberIntermediaryFrames = new Label();
        public NumericUpDown nudNumberIntermediaryFrames = new NumericUpDown();
   
        public Button btnGo = new Button();
        public Button btnCancel = new Button();

        int intIndex_Start = 0, intIndex_End = 0;

        public panelAutoInsertIntermediaryFrames() { Init(panelMoveable.fntStandard); }
        public panelAutoInsertIntermediaryFrames(Font fnt) { Init(fnt); }
        /// <summary>
        /// initializes the panel's controls
        /// </summary>
        /// <param name="fnt">font used by the panel's header</param>
        void Init(Font fnt)
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            BorderStyle = BorderStyle.Fixed3D;
            Heading.Font = fnt;
            Heading.BackColor = Color.LightGreen;
            if (frmSpriteEditor == null) frmSpriteEditor = formSpriteEditor_2017.instance;

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                     add controls to panel
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            pnlContainer.Controls.Add(picStart);

            pnlContainer.Controls.Add(lblPicStart);
            lblPicStart.AutoSize = true;

            pnlContainer.Controls.Add(picEnd);
            lblPicEnd.AutoSize = true;

            pnlContainer.Controls.Add(lblPicEnd);

            pnlContainer.Controls.Add(lblNumberIntermediaryFrames);
            lblNumberIntermediaryFrames.AutoSize = true;
            lblNumberIntermediaryFrames.Text = "Num New Frames ";

            pnlContainer.Controls.Add(nudNumberIntermediaryFrames);
            nudNumberIntermediaryFrames.Minimum = 1;
            nudNumberIntermediaryFrames.Maximum = 1024;
            nudNumberIntermediaryFrames.Font
                = lblNumberIntermediaryFrames.Font
                = new Font("Mongolian Baiti", 18, FontStyle.Regular);
            nudNumberIntermediaryFrames.MouseWheel += NudNumberIntermediaryFrames_MouseWheel;

            pnlContainer.Controls.Add(btnGo);
            btnGo.Text = "Go";
            btnGo.AutoSize = true;
            btnGo.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            pnlContainer.Controls.Add(btnCancel);
            btnCancel.Text = "Cancel";
            btnCancel.AutoSize = true;
            btnCancel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            btnCancel.Click += BtnCancel_Click;

            init_Format();

            SizeChanged += PanelAutoInsertIntermediaryFrames_SizeChanged;
            LocationChanged += PanelAutoInsertIntermediaryFrames_LocationChanged;

            placeObjects();
            setToolTip();
        }

        public void init_Format()
        {    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            ///                                         set panel's formatting variables
            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].size_Height);
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].location_Y);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].Collapsed) Collapse();
            else Expand();
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolIgnoreChanges = false;
        }

        private void NudNumberIntermediaryFrames_MouseWheel(object sender, MouseEventArgs e)
        {
            HandledMouseEventArgs handledArgs = e as HandledMouseEventArgs;
            handledArgs.Handled = true;

            NumericUpDown nudSender = (NumericUpDown)sender;
            int intNewValue = (int)nudSender.Value + (int)(handledArgs.Delta > 0 ? 1 : -1);
            if (intNewValue > nudSender.Maximum)
                nudSender.Value = nudSender.Maximum;
            else if (intNewValue < nudSender.Minimum)
                nudSender.Value = nudSender.Minimum;
            else
                nudSender.Value += (handledArgs.Delta > 0) ? 1 : -1;
        }

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

            tt.SetToolTip(lblNumberIntermediaryFrames, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblPicEnd, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblPicStart, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(picStart, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(picEnd, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(btnCancel, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(btnGo, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(nudNumberIntermediaryFrames, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// cancels operation and hides the panel
        /// </summary>
        private void BtnCancel_Click(object sender, EventArgs e) { Hide(); }

        /// <summary>
        /// launches InsertIntermediaryFrames UI for the without reinitializing the cmbLimbTracked combobox
        /// </summary>
        public void InsertIntermediaryFrames() { InsertIntermediaryFrames(false); }

        /// <summary>
        /// launches InsertIntermediaryFrames UI and reinitializes cmbLimbTracked if specified by calling function
        /// </summary>
        /// <param name="bolForceRebuildCmbLimbTracked">variable determining whether the cmbLimbTracked is reinitialized</param>
        public void InsertIntermediaryFrames(bool bolForceRebuildCmbLimbTracked)
        {
            Expand();
   
            cSpriteData= formSpriteEditor_2017.instance.cSpriteData;

            intIndex_Start = (int)formSpriteEditor_2017.instance.nudFrame_Counter.Value;
            intIndex_End = (intIndex_Start + 1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count;
            if (cSpriteData.cAnimationData.cSprite == null)
            {
                MessageBox.Show("No Sprite currently selected", "Frame AutoInsertion Error");
                return;
            }
            if (cSpriteData.cAnimationData.cAnimation == null)
            {
                MessageBox.Show("no animation currently selected", "Frame AutoInsertion Error");
                return;
            }
            if (cSpriteData.cAnimationData.cAnimation.lstFrames.Count < 2)
            {
                MessageBox.Show("the selected animation must have at least two frames", "Frame AutoInsertion Error");
                return;
            }

            cAnimation = cSpriteData.cAnimationData.cAnimation;
            cFrame_Start = cAnimation.lstFrames[cSpriteData.cAnimationData .intFrameIndex ];
            cFrame_End = cAnimation.lstFrames[(cSpriteData.cAnimationData.intFrameIndex  + 1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count];

            lblPicStart.Text = "Start Frame : " + intIndex_Start.ToString();
            lblPicEnd.Text = "End Frame : " + intIndex_End.ToString();

            placeObjects();
            Visible = true;
        }

        /// <summary>
        /// records panel's location after a location change for panel formatting purposes
        /// </summary>
        private void PanelAutoInsertIntermediaryFrames_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolInit = true;
            }
        }

        /// <summary>
        /// records panel's size after a size change for panel formatting purposes
        /// </summary>
        private void PanelAutoInsertIntermediaryFrames_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolIgnoreChanges
                && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.AutoInsertIntermediaryFrames].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// positions the panel's controls onto the panel after at initialization or sizechange
        /// </summary>
        void placeObjects()
        {
            lblPicStart.Location = classGraphics.ptZero;
            lblPicEnd.Left = pnlContainer.Width / 2;
            lblPicEnd.Top = lblPicStart.Top;

            picStart.Width = pnlContainer.Width / 2;
            picStart.Height = pnlContainer.Height - lblPicStart.Height - nudNumberIntermediaryFrames.Height - btnCancel.Height;

            if (picStart.Width < 25)
                picStart.Width = 25;
            if (picStart.Height < 25)
                picStart.Height = 25;

            picStart.Top = lblPicStart.Bottom;
            picStart.Left = 0;

            picEnd.Width = picStart.Width;
            picEnd.Height = picStart.Height;
            picEnd.Top = picStart.Top;
            picEnd.Left = picStart.Right;

            lblNumberIntermediaryFrames.Left = 0;
            lblNumberIntermediaryFrames.Top = picStart.Bottom;

            nudNumberIntermediaryFrames.Left = lblNumberIntermediaryFrames.Right;
            nudNumberIntermediaryFrames.Top = lblNumberIntermediaryFrames.Top;
            nudNumberIntermediaryFrames.Width = pnlContainer.Width - nudNumberIntermediaryFrames.Left;

            btnGo.Left = pnlContainer.Width - btnGo.Width;
            btnGo.Top = nudNumberIntermediaryFrames.Bottom;

            btnCancel.Left = btnGo.Left - btnCancel.Width;
            btnCancel.Top = btnGo.Top;

            if (cAnimation != null && cFrame_End != null && cFrame_Start != null)
            {
                drawFrame(ref picStart,  cSpriteData.cAnimationData.intFrameIndex);
                drawFrame(ref picEnd,  (cSpriteData.cAnimationData.intFrameIndex+1) % cSpriteData.cAnimationData.cAnimation.lstFrames.Count);
            }
        }

        /// <summary>
        /// draws a specified animation frame onto the picturebox provided
        /// </summary>
        /// <param name="pic">picturebox onto which the animation frame is to be drawn</param>
        /// <param name="intFrameIndex">index of current animation's frame to be drawn</param>
        void drawFrame(ref PictureBox pic, int intFrameIndex)
        {
            int intFrameIndex_Old = cSpriteData.cAnimationData.intFrameIndex;
            cSpriteData.cAnimationData.intFrameIndex = intFrameIndex;
            Bitmap bmpFrame = cSpriteData.cAnimationData.cSprite.draw_Animation_Frame(ref cSpriteData);
            cSpriteData.cAnimationData.intFrameIndex = intFrameIndex_Old;

            double dblAspectRatio_Bmp = (double)bmpFrame.Height / (double)bmpFrame.Width;
            double dblAspectRatio_Pic = (double)pic.Height / (double)pic.Width;
            int intWidth = 0;
            if (dblAspectRatio_Bmp < dblAspectRatio_Pic)
            { // limiting pic size is its width
                intWidth = pic.Width;
            }
            else
            { // limiting pic size is its height
                intWidth = (int)((double)pic.Height / dblAspectRatio_Bmp);
            }

            System.Drawing.Size szNew = new Size(intWidth, (int)((double)intWidth * dblAspectRatio_Bmp));
            Bitmap bmpPic = (Bitmap)new Bitmap(bmpFrame, szNew);
            pic.Image = bmpPic;
        }

    }
 
 

    /// <summary>
    /// graphical interface that allows the user to connect limbs and set their hinge slave/master contact values
    /// </summary>
    public class panelHingeContact_Graphical : panelMoveable
    {
        public static panelHingeContact_Graphical instance;

        public Label lblAngle_Name = new Label();
        public Label lblAngle_Value = new Label();

        public Label lblMagnitude_Name = new Label();
        public Label lblMagnitude_Value = new Label();

        /// <summary>
        /// controls that reflect the currently selected limb's hinge MasterContact values
        /// </summary>
        public GroupBox grbMaster = new GroupBox();
        public PictureBox picMaster = new PictureBox();
        public Label lblMaster_Radians = new Label();
        public Label lblMaster_Magnitude = new Label();

        /// <summary>
        /// controls that reflect the currently selected limb's hinge SlaveContact values
        /// </summary>
        public GroupBox grbSlave = new GroupBox();
        public PictureBox picSlave = new PictureBox();
        public Label lblSlave_Radians = new Label();
        public Label lblSlave_Magnitude = new Label();

        /// <summary>
        /// zoom value used to draw the master limb on screen
        /// </summary>
        double dblZoomMaster = 1.0;
        Point ptDrawTL_Master;

        /// <summary>
        ///  zoom values used to draw the slave limb on the screen
        /// </summary>
        double dblZoomSlave = 1.0;
        Point ptDrawTL_Slave;

        Point ptMouse = new Point();

        classSprite_Limb _cLimb = null;
        /// <summary>
        /// limb whose hinge connections are currently being edited
        /// </summary>
        public classSprite_Limb Limb
        {
            get { return _cLimb; }
        }


        enum enuMode { Master_Set, Slave_Set, idle }
        enuMode _eMode = enuMode.idle;
        /// <summary>
        /// edit mode is determine by user operations. 
        /// </summary>
        enuMode eMode
        {
            get { return _eMode; }
            set
            {
                _eMode = value;
            }
        }

        /// <summary>
        ///  instantiates panelHingeContact_Graphical using the standard Header font
        /// </summary>
        public panelHingeContact_Graphical() { Init(fntStandard); }
        /// <summary>
        /// instantiates panelHingeContact_Graphical using a specified Header font
        /// </summary>
        /// <param name="fnt"></param>
        public panelHingeContact_Graphical(Font fnt) { Init(fnt); }
        /// <summary>
        /// initializes the panelHingeContact_Graphical and all its component controls
        /// </summary>
        /// <param name="fnt">font used to draw the panel's header </param>
        void Init(Font fnt)
        {
            instance = this;
            Heading.Font = fnt;
            Heading.Text = "Hinge Contact";
            Heading.BackColor = Color.LightSkyBlue;
            BackColor = Color.White;
            BorderStyle = BorderStyle.Fixed3D;


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

            picMaster.Name = "picMaster";
            grbMaster.Controls.Add(picMaster);

            lblMaster_Radians.AutoSize = true;
            lblMaster_Radians.Name = "lblMaster_Radians";
                grbMaster.Controls.Add(lblMaster_Radians);

            lblMaster_Magnitude.AutoSize = true;
            lblMaster_Magnitude.Name = "lblMaster_Magnitude";
            grbMaster.Controls.Add(lblMaster_Magnitude);

            picMaster.Name = "picMaster";
            picMaster.MouseMove += PicMaster_MouseMove;
            picMaster.MouseClick += PicMaster_MouseClick;
            picMaster.MouseWheel += PicMaster_MouseWheel;

            grbSlave.Name = "grbSlave";
            pnlContainer.Controls.Add(grbSlave);
            picSlave.Name = "picSlave";
            grbSlave.Controls.Add(picSlave);

            lblMaster_Radians.Name = "lblMaster_Radians";
            lblMaster_Radians.AutoSize = true;
            grbSlave.Controls.Add(lblSlave_Radians);

            lblMaster_Magnitude.Name = "lblMaster_Magnitude";
            lblMaster_Magnitude.AutoSize = true;
            grbSlave.Controls.Add(lblSlave_Magnitude); 

            picSlave.MouseMove += PicSlave_MouseMove;
            picSlave.MouseClick += PicSlave_MouseClick;
            picSlave.MouseWheel += PicSlave_MouseWheel;

            lblAngle_Name.Name = "lblAngle_Name";
            lblAngle_Name.Text = "Angle :";
            pnlContainer.Controls.Add(lblAngle_Name);

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

            lblMagnitude_Name.Name = "lblMagnitude_Name";
            lblMagnitude_Name.Text = "Magnitude :";
            pnlContainer.Controls.Add(lblMagnitude_Name);

            lblMagnitude_Value.Name = "lblMagnitude_Value";
            pnlContainer.Controls.Add(lblMagnitude_Value);
            init_Format();

            
            SizeChanged += panelHingeContact_Graphical_SizeChanged;
            LocationChanged += panelHingeContact_Graphical_LocationChanged;
            Disposed += panelHingeContact_Graphical_Disposed;
            BringToFront();
            placeObjects();
            setToolTip();
        }

        public void init_Format()
        {

            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].size_Width,
                            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].size_Height);

            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].ExpansionDirection;

            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolIgnoreChanges = false;
        }

        /// <summary>
        /// binds controls to the formSpriteEditor2017's tooltip
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            string strAngle = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblAngle_Name, strAngle);
            tt.SetToolTip(lblAngle_Value, strAngle);

            string strMagnitudes = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(lblMagnitude_Name, strMagnitudes);
            tt.SetToolTip(lblMagnitude_Value, strMagnitudes);

            string strMasterContact = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(grbMaster, strMasterContact);
            tt.SetToolTip(picMaster, strMasterContact);

            tt.SetToolTip(lblMaster_Radians, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblMaster_Magnitude, formSpriteEditor_2017.conDefaultToolTip);
            string strSlaveContact = formSpriteEditor_2017.conDefaultToolTip;
            tt.SetToolTip(grbSlave, strSlaveContact);
            tt.SetToolTip(picSlave, strSlaveContact);

        }

        /// <summary>
        /// zooms in/out using mouseWheel UI
        /// </summary>
        const double conMaxZoom = 100;
        private void PicSlave_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta < 0)
            {   
                dblZoomSlave /= 1.1;
                if (dblZoomSlave > conMaxZoom)
                    dblZoomSlave = conMaxZoom;
            }
            else
            {
                dblZoomSlave *= 1.1;
            }
            drawSlave();
        }

        /// <summary>
        /// zooms in/out using MouseWheel UI
        /// </summary>
        private void PicMaster_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta < 0)
            {
                dblZoomMaster /= 1.1;
                if (dblZoomMaster > conMaxZoom)
                    dblZoomMaster = conMaxZoom;
            }
            else
            {
                dblZoomMaster *= 1.1;
            }
            drawMaster();
        }

        /// <summary>
        /// records the panel's collapsed/ExpansionDirection states for formatting purposes
        /// </summary>
        private void panelHingeContact_Graphical_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].Collapsed = Collapsed;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].ExpansionDirection = ExpansionDirection;
        }

        /// <summary>
        /// records panel's location after a location change for formatting purposes
        /// </summary>
        private void panelHingeContact_Graphical_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].location_Y = Location.Y;
            }
        }

        //records panel's size after a sizechange for formatting purposes
        private void panelHingeContact_Graphical_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolIgnoreChanges
                 && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].size_Height = Size.Height;
            }

            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Graphical].Collapsed = Collapsed;
            placeObjects();
        }

        /// <summary>
        /// sets the currently selected limb's hinge values to reflect recent edits made by the user with the panel's graphical UI
        /// </summary>
        /// <param name="limb"></param>
        public void setLimbContact(ref classSprite_Limb limb)
        {
            if (limb.Hinge == null) return;
            _cLimb = limb;
            Heading.Text = _cLimb.Hinge.Limb_Slave.Name;


            if (limb.Hinge != null)
            {
                grbMaster.Text = limb.Hinge.Limb_Master.Name;
                grbSlave.Text = limb.Name;
                drawMaster();
                drawSlave();
                setText_Labels_Slave();
                setText_Labels_Master();
                placeObjects();
                if (formSpriteEditor_2017.instance.mnuPanels_HingeContact_Graphical.Checked)
                    Show();
            }
        }

        /// <summary>
        /// changes the eMode to reflect the user's intentions after clicking on the masterContact's graphical UI picturebox
        /// </summary>
        private void PicMaster_MouseClick(object sender, MouseEventArgs e)
        {
            switch (eMode)
            {
                case enuMode.idle:
                    eMode = enuMode.Master_Set;
                    break;

                case enuMode.Master_Set:
                    if (_cLimb != null)
                    {
                        setText_Labels_Master();
                        eMode = enuMode.idle;
                        drawMaster();
                    }
                    break;

                default:
                    break;
            }
        }

        double dblMasterDrawSizeFactor = 1.0;
        /// <summary>
        /// draws the hinge's MasterContact onto the Master Hinge's graphical UI picturebox
        /// </summary>
        public void drawMaster()
        {
            if (_cLimb != null
                && _cLimb.Hinge != null
                && _cLimb.Hinge.Limb_Master != null
                && picMaster.Width > 0
                && picMaster.Height > 0)
            {
                Bitmap bmpMaster = _cLimb.Hinge.Limb_Master.lstImages[_cLimb.Hinge.Limb_Master.intImageList_Index].bmpImages[0];
                
                Rectangle recSource = new Rectangle(classGraphics.ptZero, bmpMaster.Size);

                double dblBmpAspectRatio = (double)bmpMaster.Height / (double)bmpMaster.Width;
                double dblPicAspectRatio = (double)picMaster.Height / (double)picMaster.Width;

                if (dblBmpAspectRatio > dblPicAspectRatio)
                { // limit is height
                    dblMasterDrawSizeFactor = (double)picMaster.Height / (double)bmpMaster.Height;
                }
                else
                { // limit is width
                    dblMasterDrawSizeFactor = (double)picMaster.Width / (double)bmpMaster.Width;
                }

                dblMasterDrawSizeFactor *= dblZoomMaster;

                Size szDestination = new Size((int)((double)bmpMaster.Width * dblMasterDrawSizeFactor),
                                              (int)((double)bmpMaster.Height * dblMasterDrawSizeFactor));
                Point ptDestination = new Point(ptDrawTL_Master.X - szDestination.Width / 2, ptDrawTL_Master.Y - szDestination.Height / 2);

                Rectangle recDestion = new Rectangle(ptDestination, szDestination);

                Bitmap bmpTemp = new Bitmap(picMaster.Width, picMaster.Height);
                using (Graphics g = Graphics.FromImage(bmpTemp))
                {
                    g.FillRectangle(Brushes.White, new Rectangle(classGraphics.ptZero, picMaster.Size));
                    g.DrawImage(bmpMaster, recDestion, recSource, GraphicsUnit.Pixel);


                    ptDrawTL_Master.X = recDestion.Left + recDestion.Width / 2;
                    ptDrawTL_Master.Y = recDestion.Top + recDestion.Height / 2;
                    switch (eMode)
                    {
                        case enuMode.idle:
                            {
                                Point ptHingeMaster = classMath3.AddTwoPoints(ptDrawTL_Master, classMath3.RadToPt(new classRadialCoordinate(_cLimb.Hinge.Contact.Master.Radians, _cLimb.Hinge.Contact.Master.Magnitude * dblMasterDrawSizeFactor), 0));
                                double dblSlope = (double)(ptDrawTL_Master.Y - ptHingeMaster.Y) / (double)(ptDrawTL_Master.X - ptHingeMaster.X);
                                Point ptShift = dblSlope > 0.75 && dblSlope < 1.25
                                                                    ? new Point(-1, 1)
                                                                    : new Point(1, 1);
                                g.DrawLine(Pens.Black, new Point(ptDrawTL_Master.X + ptShift.X, ptDrawTL_Master.Y + ptShift.Y), new Point(ptHingeMaster.X + ptShift.X, ptHingeMaster.Y + ptShift.Y));
                                g.DrawLine(Pens.Green, ptDrawTL_Master, ptHingeMaster);
                            }
                            break;

                        case enuMode.Master_Set:
                            {
                                double dblSlope =(double)(ptDrawTL_Master.Y - ptMouse.Y) / (double)(ptDrawTL_Master.X - ptMouse.X);
                                Point ptShift = dblSlope > 0.75 && dblSlope < 1.25
                                                                    ? new Point(-1, 1)
                                                                    : new Point (1,1);
                                g.DrawLine(Pens.Black, new Point(ptDrawTL_Master.X + ptShift.X , ptDrawTL_Master.Y +ptShift.Y ), new Point(ptMouse.X +ptShift.X , ptMouse.Y +ptShift.Y ));
                                g.DrawLine(Pens.Red, ptDrawTL_Master, ptMouse);
                            }
                            break;

                        default:
                            break;

                    }
                }
                picMaster.Image = bmpTemp;
            }
        }

        /// <summary>
        /// sets the eMode to reflect user's intention after a mouse click of the hinge's slaveContact graphical UI picturebox
        /// </summary>
        private void PicSlave_MouseClick(object sender, MouseEventArgs e)
        {
            switch (eMode)
            {
                case enuMode.idle:
                    eMode = enuMode.Slave_Set;
                    break;

                case enuMode.Slave_Set:
                    if (_cLimb != null)
                    {
                        eMode = enuMode.idle;
                        setText_Labels_Slave();
                        drawSlave();
                    }
                    break;

                default:
                    break;

            }
        }

        double dblSlaveDrawSizeFactor = 1.0;
        /// <summary>
        /// draws the hinge's slaveContact onto the slaveContact graphical UI picturebox
        /// </summary>
        public void drawSlave()
        {
            if (_cLimb != null
               && _cLimb.Hinge != null
               && _cLimb.Hinge.Limb_Master != null
               && picSlave.Width > 0
               && picSlave.Height > 0)
            {
                Bitmap bmpSlave = _cLimb.Hinge.Limb_Slave.lstImages[_cLimb.intImageList_Index].bmpImages[0];
                Rectangle recSource = new Rectangle(classGraphics.ptZero, bmpSlave.Size);
                double dblBmpAspectRatio = (double)bmpSlave.Height / (double)bmpSlave.Width;
                double dblPicAspectRatio = (double)picSlave.Height / (double)picSlave.Width;

                if (dblBmpAspectRatio > dblPicAspectRatio)
                { // limit is height
                    dblSlaveDrawSizeFactor = (double)picSlave.Height / (double)bmpSlave.Height;
                }
                else
                { // limit is width
                    dblSlaveDrawSizeFactor = (double)picSlave.Width / (double)bmpSlave.Width;
                }

                dblSlaveDrawSizeFactor *= dblZoomSlave;

                Size szDestination = new Size((int)((double)bmpSlave.Width * dblSlaveDrawSizeFactor),
                                        (int)((double)bmpSlave.Height * dblSlaveDrawSizeFactor));
                Point ptDestination = new Point(ptDrawTL_Slave.X - szDestination.Width / 2, ptDrawTL_Slave.Y - szDestination.Height / 2);
                Rectangle recDestion = new Rectangle(ptDestination, szDestination);

                Bitmap bmpTemp = new Bitmap(picSlave.Width, picSlave.Height);
                using (Graphics g = Graphics.FromImage(bmpTemp))
                {
                    g.FillRectangle(Brushes.White, new Rectangle(classGraphics.ptZero, picSlave.Size));
                    g.DrawImage(bmpSlave, recDestion, recSource, GraphicsUnit.Pixel);
                    ptDrawTL_Slave.X = recDestion.Left + recDestion.Width / 2;
                    ptDrawTL_Slave.Y = recDestion.Top + recDestion.Height / 2;
                    switch (eMode)
                    {
                        case enuMode.idle:
                            {
                                Point ptHingeSlave = classMath3.AddTwoPoints(ptDrawTL_Slave, classMath3.RadToPt(new classRadialCoordinate(_cLimb.Hinge.Contact.Slave.Radians, _cLimb.Hinge.Contact.Slave.Magnitude * dblSlaveDrawSizeFactor), Math.PI));
                                double dblSlope = (double)(ptDrawTL_Slave.Y - ptHingeSlave.Y) / (double)(ptDrawTL_Slave.X - ptHingeSlave.X);
                                Point ptShift = dblSlope > 0.75 && dblSlope < 1.25
                                                                    ? new Point(-1, 1)
                                                                    : new Point(1, 1);
                                g.DrawLine(Pens.Black, new Point(ptDrawTL_Slave.X + ptShift.X, ptDrawTL_Slave.Y + ptShift.Y), new Point(ptHingeSlave.X + ptShift.X, ptHingeSlave.Y + ptShift.Y));
                                g.DrawLine(Pens.Green, ptDrawTL_Slave, ptHingeSlave);
                            }
                            break;

                        case enuMode.Slave_Set:
                            {
                                double dblSlope = (double)(ptDrawTL_Slave.Y - ptMouse.Y) / (double)(ptDrawTL_Slave.X - ptMouse.X);
                                Point ptShift = dblSlope > 0.75 && dblSlope < 1.25
                                                                    ? new Point(-1, 1)
                                                                    : new Point(1, 1);
                                g.DrawLine(Pens.Black, new Point(ptDrawTL_Slave.X + ptShift.X, ptDrawTL_Slave.Y + ptShift.Y), new Point(ptMouse.X + ptShift.X, ptMouse.Y + ptShift.Y));
                                g.DrawLine(Pens.Red, ptDrawTL_Slave, ptMouse);
                            }
                            break;

                    }


                }
                picSlave.Image = bmpTemp;
            }
        }

        /// <summary>
        /// responds to mousemove over MasterContact picturebox and sets the hinge's MasterContact during editing operation
        /// </summary>
        private void PicMaster_MouseMove(object sender, MouseEventArgs e)
        {
            ptMouse.X = e.X;
            ptMouse.Y = e.Y;
            if (eMode == enuMode.Master_Set)
            {
                setText_Labels_Master();
                _cLimb.Hinge.Contact.Master = classMath3.CarToRad(classMath3.SubTwoPoints(ptMouse, ptDrawTL_Master));
                _cLimb.Hinge.Contact.Master.Magnitude /= dblMasterDrawSizeFactor;
                drawMaster();
            }
        }

        /// <summary>
        /// responds to mousemove over SlaveContact picturebox and sets the hinge's SlaveContact during editing operation
        /// </summary>
        private void PicSlave_MouseMove(object sender, MouseEventArgs e)
        {
            ptMouse.X = e.X;
            ptMouse.Y = e.Y;
            if (eMode == enuMode.Slave_Set)
            {
                drawSlave();
                _cLimb.Hinge.Contact.Slave = classMath3.CarToRad(classMath3.SubTwoPoints(ptDrawTL_Slave, ptMouse));
                _cLimb.Hinge.Contact.Slave.Magnitude /= dblSlaveDrawSizeFactor;
                setText_Labels_Slave();
            }
        }

        /// <summary>
        /// updates the labels pertaining to the limb's hinge Slavecontact state
        /// </summary>
        void setText_Labels_Slave()
        {
            if (_cLimb != null
                && _cLimb.Hinge != null
                && _cLimb.Hinge.Limb_Slave != null)
            {
                string strValue_Magnitude = _cLimb.Hinge.Contact.Slave.Magnitude.ToString(strMagnitudeFormat);
                formSpriteEditor_2017.instance.txtHinge_Contact_Slave_Magnitude.Text = strValue_Magnitude;
                lblSlave_Magnitude.Text = "Mag:" + strValue_Magnitude;

                string strValue_Radians = _cLimb.Hinge.Contact.Slave.Radians.ToString(strRadiansFormat);
                formSpriteEditor_2017.instance.txtHinge_Contact_Slave_Radians.Text = strValue_Radians;
                lblSlave_Radians.Text = "Rad:" + strValue_Radians;

            }
        }

        /// <summary>
        /// updates the labels pertaining to the limb's hinge MasterContact state
        /// </summary>
        void setText_Labels_Master()
        {
            if (_cLimb != null
                && _cLimb.Hinge != null
                && _cLimb.Hinge.Limb_Master != null)
            {
                string strValue_Magnitude = _cLimb.Hinge.Contact.Master.Magnitude.ToString(strMagnitudeFormat);
                formSpriteEditor_2017.instance.txtHinge_Contact_Master_Magnitude.Text = strValue_Magnitude;
                lblMaster_Magnitude.Text = "Mag:" + strValue_Magnitude;

                string strValue_Radians = _cLimb.Hinge.Contact.Master.Radians.ToString(strRadiansFormat);
                formSpriteEditor_2017.instance.txtHinge_Contact_Master_Radians.Text = strValue_Radians;
                lblMaster_Radians.Text = "Rad:" + strValue_Radians;
            }
        }

        /// <summary>
        /// strings used to format the Costume of textboxes displaying radian variable values
        /// </summary>
        string strRadiansFormat = formSpriteEditor_2017.strRadiansFormat;

        /// <summary>
        /// strings used to format the Costume of tetboxes displaying magnitude variable values
        /// </summary>
        string strMagnitudeFormat = formSpriteEditor_2017.strMagnitudeFormat;

        /// <summary>
        ///  positions controls onto the panel
        /// </summary>
        void placeObjects()
        {
            Size szPanel = new Size();
            szPanel.Height = pnlContainer.Height;
            szPanel.Width = pnlContainer.Width;

            lblAngle_Name.Location = new Point(1, 0);
            lblAngle_Value.Location = new Point(lblAngle_Name.Right + 1, lblAngle_Name.Top);

            lblMagnitude_Name.Location = new Point(szPanel.Width / 2 + 2, lblAngle_Name.Top);
            lblMagnitude_Value.Location = new Point(lblMagnitude_Name.Right + 1, lblMagnitude_Value.Top);

            grbMaster.Location = new Point(0, lblAngle_Name.Bottom + 2);
            grbMaster.Text = "Master Limb (" + (_cLimb != null
                                                && _cLimb.Hinge != null
                                                      ? _cLimb.Hinge.Limb_Master.Name + ")"
                                                      : "no limb loaded");
            grbMaster.Size = new Size((szPanel.Width) / 2, szPanel.Height - grbMaster.Top);
            lblMaster_Radians.Location = new Point(0, 20);
            lblMaster_Magnitude.Location = new Point(lblMaster_Radians.Right + 1, lblMaster_Radians.Top);
            picMaster.Location = new Point(lblMaster_Radians.Left + 2, lblMaster_Radians.Bottom + 1);
            picMaster.Size = new Size(grbMaster.Width - 4, grbMaster.Height - picMaster.Top);
            ptDrawTL_Master.X = picMaster.Width / 2;
            ptDrawTL_Master.Y = picMaster.Height / 2;

            grbSlave.Location = new Point(grbMaster.Right + 1, grbMaster.Top);
            grbSlave.Text = "Slave Limb (" + (_cLimb != null
                                                && _cLimb.Hinge != null
                                                      ? _cLimb.Hinge.Limb_Slave.Name + ")"
                                                      : "no limb loaded");
            grbSlave.Size = grbMaster.Size;
            lblSlave_Radians.Location = lblMaster_Radians.Location;
            lblSlave_Radians.Width = lblMaster_Radians.Width;
            lblSlave_Magnitude.Location = lblMaster_Magnitude.Location;
            lblSlave_Magnitude.Width = lblMaster_Magnitude.Width;
            picSlave.Location = picMaster.Location;
            picSlave.Size = picMaster.Size;
            ptDrawTL_Slave.X = picSlave.Width / 2;
            ptDrawTL_Slave.Y = picSlave.Height / 2;

            if (_cLimb != null
                && _cLimb.Hinge != null
                && _cLimb.Hinge.Limb_Master != null)
            {
                lblMaster_Radians.Text = "Rad:" + _cLimb.Hinge.Contact.Master.Radians.ToString(strRadiansFormat);
                lblMaster_Magnitude.Text = "Mag:" + _cLimb.Hinge.Contact.Master.Magnitude.ToString(strMagnitudeFormat);
            }

            drawMaster();
            drawSlave();

            setText_Labels_Slave();
            setText_Labels_Master();
        }
    }

    /// <summary>
    /// panel allows the user to edit the currently selected limb's hinge Contact values
    /// </summary>
    public class panelHingeContact_Numerical : panelMoveable
    {
        public GroupBox grbMaster;
        public GroupBox grbSlave;
        public Label lblSlave_Rad;
        public TextBox txtSlave_Rad;
        public Label lblSlave_Mag;
        public TextBox txtSlave_Mag;

        public Label lblMaster_Rad;
        public TextBox txtMaster_Rad;
        public Label lblMaster_Mag;
        public TextBox txtMaster_Mag;

        /// <summary>
        /// instantiates a panelHingeContact_Numerical with standard Header font
        /// </summary>
        public panelHingeContact_Numerical() { Init(fntStandard); }
        /// <summary>
        /// instantiates a panelHingeContact_Numerical with a specified Header font
        /// </summary>
        /// <param name="fnt">font used to draw the panel's Header</param>
        public panelHingeContact_Numerical(Font fnt)
        {
            Init(fnt);
        }

        /// <summary>
        /// initializes all of panelHingeContact_Numerical's controls
        /// </summary>
        /// <param name="fnt">font used to draw the panel's Header</param>
        void Init(Font fnt)
        {
            grbMaster = formSpriteEditor_2017.instance.grbLimbEditor_Hinge_Contact_Master;
            lblMaster_Mag = formSpriteEditor_2017.instance.lblHinge_Contact_Master_Magnitude;
            txtMaster_Mag = formSpriteEditor_2017.instance.txtHinge_Contact_Master_Magnitude;
            lblMaster_Rad = formSpriteEditor_2017.instance.lblHinge_Contact_Master_Radians;
            txtMaster_Rad = formSpriteEditor_2017.instance.txtHinge_Contact_Master_Radians;

            grbSlave = formSpriteEditor_2017.instance.grbLimbEditor_Hinge_Contact_Slave;
            lblSlave_Mag = formSpriteEditor_2017.instance.lblHinge_Contact_Slave_Magnitude;
            txtSlave_Mag = formSpriteEditor_2017.instance.txtHinge_Contact_Slave_Magnitude;
            lblSlave_Rad = formSpriteEditor_2017.instance.lblHinge_Contact_Slave_Radians;
            txtSlave_Rad = formSpriteEditor_2017.instance.txtHinge_Contact_Slave_Radians;

            Heading.Font = fnt;
            Heading.Text = "Hinge Contacts";
            Heading.BackColor
                = pnlContainer.BackColor
                = grbMaster.BackColor
                = grbSlave.BackColor
                = lblSlave_Rad.BackColor
                = txtSlave_Rad.BackColor
                = lblSlave_Mag.BackColor
                = txtSlave_Mag.BackColor
                = lblMaster_Rad.BackColor
                = txtMaster_Rad.BackColor
                = lblMaster_Mag.BackColor
                = txtMaster_Mag.BackColor
                = Color.LightBlue;

            Heading.ForeColor
                = pnlContainer.ForeColor
                = grbMaster.ForeColor
                = grbSlave.ForeColor
                = lblSlave_Rad.ForeColor
                = txtSlave_Rad.ForeColor
                = lblSlave_Mag.ForeColor
                = txtSlave_Mag.ForeColor
                = lblMaster_Rad.ForeColor
                = txtMaster_Rad.ForeColor
                = lblMaster_Mag.ForeColor
                = txtMaster_Mag.ForeColor
                = Color.Black;


            pnlContainer.Controls.Add(grbMaster);
            pnlContainer.Controls.Add(grbSlave);
            grbSlave.BringToFront();
            grbMaster.BringToFront();

            // binds the panel's controls to the formSpriteEditor_2017's tooltip
            setToolTip();

            init_Format();

            SizeChanged += panelHingeContact_Numerical_SizeChanged;
            LocationChanged += panelHingeContact_Numerical_LocationChanged;
            Disposed += panelHingeContact_Numerical_Disposed;
        }

        public void init_Format()
        { //  formats the panel according to values loaded in format_load() earlier
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].size_Height);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].ExpansionDirection;
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].bolIgnoreChanges = false;

            placeObjects();
        }

        /// <summary>
        /// binds panel's controls to the formSpriteEditor_2017's tooltip
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            // pnlHingeContact_Numerical
            tt.SetToolTip(grbMaster, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(grbSlave, formSpriteEditor_2017.conDefaultToolTip);

             tt.SetToolTip(lblSlave_Rad, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtSlave_Rad, formSpriteEditor_2017.conDefaultToolTip);

             tt.SetToolTip(lblSlave_Mag, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtSlave_Mag, formSpriteEditor_2017.conDefaultToolTip);

             tt.SetToolTip(lblMaster_Rad, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtMaster_Rad, formSpriteEditor_2017.conDefaultToolTip);

             tt.SetToolTip(lblMaster_Mag, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtMaster_Mag, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// records panel's current Collapsed/ExpansionDirection variables for later formatting purposes
        /// </summary>
        private void panelHingeContact_Numerical_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].Collapsed = Collapsed;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.HingeContact_Numerical].ExpansionDirection = ExpansionDirection;
        }

        /// <summary>
        /// records panels location after a location change for formatting purposes
        /// </summary>
        private void panelHingeContact_Numerical_LocationChanged(object sender, EventArgs e)
        {

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

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void panelHingeContact_Numerical_SizeChanged(object sender, EventArgs e)
        {

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

            placeObjects();
        }

        /// <summary>
        /// resizes the objects inside the panel's HingeContact groupbox
        /// </summary>
        private void GrbLimbEditor_Hinge_Contact_SizeChanged(object sender, EventArgs e)
        {
            placeObjects();
        }

        /// <summary>
        /// places panels controls when instantiated and every size change
        /// </summary>
        void placeObjects()
        {
            grbMaster.Width
                = grbSlave.Width
                = pnlContainer.Width - 4;
            grbMaster.Left
                 = grbSlave.Left
                 = 2;

            grbMaster.Height
                = grbSlave.Height
                = pnlContainer.Height / 2;

            grbMaster.Top = 0;
            grbSlave.Top = grbMaster.Bottom;

            lblMaster_Mag.Left
               = lblMaster_Rad.Left
               = lblSlave_Mag.Left
               = lblSlave_Rad.Left
               = 2;

            lblMaster_Mag.Width
                = lblMaster_Rad.Width
                = lblSlave_Mag.Width
                = lblSlave_Rad.Width
                = txtMaster_Rad.Width
                = txtMaster_Mag.Width
                = txtSlave_Mag.Width
                = txtSlave_Rad.Width
                = grbMaster.Width / 2 - 2;

        }
    }

    /// <summary>
    /// panel displays currently selected limb's list of images which can be then edited
    /// </summary>
    public class panelLimb_ImageController : panelMoveable
    {
        public static panelLimb_ImageController instance;

        /// <summary>
        /// panel that holds a single image from the limb's list of images
        /// </summary>
        public class panelImageDisplay : Panel
        {
            public Label lblName = new Label();
            public TextBox txtName = new TextBox();
            public PictureBox pic = new PictureBox();
            public Button btnDelete = new Button();

            /// <summary>
            /// a panel is needed for the VerticalScrolling panel and contains panelImageDisplay before being added to the scrollingVPanel
            /// </summary>
            public Panel pnlMyContainer;

            public classSprite_Limb.classSprite_Limb_Images LimbImage = null;

            classSprite_Limb cLimb = null;
            public classSprite_Limb Limb
            {
                get { return cLimb; }
                set
                {
                    if (cLimb != value)
                    {
                        cLimb = value;
                    }
                }
            }

            /// <summary>
            /// instantiates one image panel of this limb for the user to edit or delete
            /// </summary>
            /// <param name="cLimb"></param>
            /// <param name="cLimbImage"></param>
            public panelImageDisplay(ref classSprite_Limb cLimb, ref classSprite_Limb.classSprite_Limb_Images cLimbImage)
            {
                Dock = DockStyle.Fill;
                BorderStyle = BorderStyle.Fixed3D;

                Limb = cLimb;
                LimbImage = cLimbImage;

                lblName.Text = "Name";
                lblName.AutoSize = true;
                Controls.Add(lblName);

                btnDelete.Text = "Delete";
                btnDelete.Visible = cLimb.lstImages.Count > 1;
                btnDelete.Click += BtnDelete_Click;
                Controls.Add(btnDelete);

                pic.SizeMode = PictureBoxSizeMode.Zoom;
                pic.Image = cLimbImage.bmpImages[0];
                pic.Click += Pic_Click;
                pic.MouseWheel += Pic_MouseWheel;
                Controls.Add(pic);

                Height = pic.Image.Height + btnDelete.Height + txtName.Height;

                //    txtName.KeyDown 
                txtName.Text = cLimbImage.Name;
                txtName.BackColor = Color.White;
                txtName.KeyPress += TxtName_KeyPress;
                txtName.TextChanged += TxtName_TextChanged;
                Controls.Add(txtName);

                setToolTip();

                SizeChanged += PanelImageDisplay_SizeChanged;
            }

            /// <summary>
            /// binds this panel's controls to the formSpriteEditor_2017's tooltip
            /// </summary>
            void setToolTip()
            {
                ToolTip tt = formSpriteEditor_2017.instance.toolTip;
                tt.SetToolTip(lblName, formSpriteEditor_2017.conDefaultToolTip);
                tt.SetToolTip(txtName, formSpriteEditor_2017.conDefaultToolTip);

                tt.SetToolTip(pic, formSpriteEditor_2017.conDefaultToolTip);
                tt.SetToolTip(btnDelete, formSpriteEditor_2017.conDefaultToolTip);
            }

            /// <summary>
            /// calls parent class' function that scrolls this panel's VScrollingPanel container
            /// </summary>
            private void Pic_MouseWheel(object sender, MouseEventArgs e)
            {
                panelLimb_ImageController.instance._MouseWheel(sender, e);
            }

            /// <summary>
            /// picturebox mouseClick allows the user to select a new image to replace the currently used image
            /// </summary>
            private void Pic_Click(object sender, EventArgs e)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Title = "Select new image for " + Limb.Name + "'s image " + LimbImage.Name;
                if (formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo != formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default)
                {
                    classSprite_Limb cLimb_Default = (classSprite_Limb)formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.cBT_Limbs.Search(Limb.Name);
                    if (cLimb_Default == Limb)
                    {
                        // this costume does not have this limb and points to the original
                        if (MessageBox.Show("The costume \r\n\t\t"
                                                + formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo.Name
                                                + "\r\n does not have its own images for the limb \r\n\t\t"
                                                + Limb.Name
                                                + "\r\n changing this image will change the default costume's image."
                                                + "\r\nDo you want to change the default costume's image?",
                                            "default costume image",
                                            MessageBoxButtons.YesNo) 
                            == DialogResult.No)
                            return;
                    }
                }
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    bolMouseControl = panelFrameEditor.instance.chkMouse_LimbControl.Checked;
                    panelFrameEditor.instance.chkMouse_LimbControl.Checked = false;

                    Bitmap bmpNewImage = null;

                    try
                    {
                        bmpNewImage = (Bitmap)Bitmap.FromFile(ofd.FileName);
                    }
                    catch (Exception err)
                    {
                        MessageBox.Show("There was an error loading the image \r\n\t" + ofd.FileName + "\r\n error:" + err.Message, "Error loading image");
                        panelFrameEditor.instance.chkMouse_LimbControl.Checked = bolMouseControl;

                        return;
                    }
                    formSpriteEditor_2017.instance.Enabled = false;

                    LimbImage.bmpImages[0] = bmpNewImage;

                    classSprite_Limb cLimb = formSpriteEditor_2017.instance.cLimb;
                    
                    classSprite_Limb.GenerateFirstQuadrantImages(ref LimbImage, formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.NumImagesPerQuadrant);
                    pic.Image = LimbImage.bmpImages[0];
                    pnlMyContainer.Height = LimbImage.bmpImages[0].Height + panelLimb_ImageController.conScrollingPanelContainerHeight_LessImageHeight;
                    panelLimb_ImageController.instance.ScrollingPanel_Refresh();
                    panelHingeContact_Graphical.instance.setLimbContact(ref cLimb);
                    formSpriteEditor_2017.instance.Draw_Sprite();
                    panelFrameEditor.instance.chkMouse_LimbControl.Checked = bolMouseControl;
                    formSpriteEditor_2017.instance.Enabled = true;
                    formSpriteEditor_2017.instance.BringToFront();
                    formSpriteEditor_2017.instance.IgnoreMouseMove();
                }
            }
            bool bolMouseControl = false;

            void BckRotate_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
            {
                pic.Image = LimbImage.bmpImages[0];
                pnlMyContainer.Height = LimbImage.bmpImages[0].Height + panelLimb_ImageController.conScrollingPanelContainerHeight_LessImageHeight;
                panelLimb_ImageController.instance.ScrollingPanel_Refresh();
                panelHingeContact_Graphical.instance.setLimbContact(ref cLimb);
                formSpriteEditor_2017.instance.Draw_Sprite();
                panelFrameEditor.instance.chkMouse_LimbControl.Checked = bolMouseControl;
                formSpriteEditor_2017.instance.Enabled = true;
                formSpriteEditor_2017.instance.BringToFront();
                formSpriteEditor_2017.instance.IgnoreMouseMove();

                
            }


            /// <summary>
            /// deletes this image from the image list if there is at least more image in this limb's image list
            /// </summary>
            private void BtnDelete_Click(object sender, EventArgs e)
            {
                if (Limb.lstImages.Count < 2)
                {
                    MessageBox.Show("This limb has only one image.  You cannot delete the limb's only image.", "Error");
                    return;
                }

                if (MessageBox.Show("Are you sure you want to delete this image?", "Delete Image", MessageBoxButtons.OKCancel) == DialogResult.OK)
                {
                    classSprite_CostumeInfo cCostume_Temp = formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo;
                    formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default;

                    Limb.lstImages.Remove(LimbImage);
                    Limb.intImageList_Index = 0;

                    for (int intCostumeCounter = 0; intCostumeCounter < formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo.Count; intCostumeCounter++)
                    {
                        classSprite_CostumeInfo cCostume = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo[intCostumeCounter];
                        classSprite_Limb cLimb_Costume = (classSprite_Limb)cCostume.cBT_Limbs.Search(Limb.Name);
                        if (cLimb_Costume != null)
                        {
                            classSprite_Limb.classSprite_Limb_Images cLimbImages_Costume = (classSprite_Limb.classSprite_Limb_Images)cLimb_Costume.cBT_LimbImages.Search(LimbImage.Name);
                            cLimb_Costume.lstImages.Remove(cLimbImages_Costume);
                            cLimb_Costume.intImageList_Index = 0;
                        }
                    }

                    RebuildAlphaTree();

                    Panel pnlContainer = pnlMyContainer;
                    panelLimb_ImageController.instance.pnlScrolling.SubPanel(ref pnlContainer);

                    classSprite cSprite = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite;
                    for (int intAnimationCounter = 0; intAnimationCounter < cSprite.lstAnimations.Count; intAnimationCounter++)
                    {
                        classAnimation cAnimation = cSprite.lstAnimations[intAnimationCounter];

                        for (int intFrameCounter = 0; intFrameCounter < cAnimation.lstFrames.Count; intFrameCounter++)
                        {
                            classAnimation_Frame cFrame = cAnimation.lstFrames[intFrameCounter];

                            for (int intDataCounter = 0; intDataCounter < cFrame.lstData.Count; intDataCounter++)
                            {
                                classAnimation_Frame_LimbData cData = cFrame.lstData[intDataCounter];
                                if (cSprite.cCostumeInfo_Default.lstLimbs[ cData.intLimbIndex ]== Limb)
                                {
                                    cData.ImageList_Index = 0;
                                    break;
                                }
                            }
                        }
                    }
                    formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo = cCostume_Temp;
                }
            }

            /// <summary>
            /// rebuilds the alphaTree that tracks limb's LimbImages by name
            /// </summary>
            void RebuildAlphaTree()
            {
                // rebuild AlphaTree
                cLimb.cBT_LimbImages = new BinTree.classBinTree();
                for (int intImageCounter = 0; intImageCounter < cLimb.lstImages.Count; intImageCounter++)
                {
                    classSprite_Limb.classSprite_Limb_Images cLimbImages = cLimb.lstImages[intImageCounter];

                    object objLimbImages = (object)cLimbImages;
                    cLimb.cBT_LimbImages.Insert(ref objLimbImages, cLimbImages.Name);
                }
            }

            /// <summary>
            /// allows the user to edit the name of a limb image while limiting the characters useable for a viable limb image name
            /// </summary>
            private void TxtName_KeyPress(object sender, KeyPressEventArgs e)
            {
                if (!classSprite_Limb.ValidLimbNameChar.Contains(char.ToUpper(e.KeyChar)))
                {
                    if (e.KeyChar != '\b')
                        e.Handled = true;
                    if (e.KeyChar == '\r')
                    {
                        if (!NameInListAlready(txtName.Text))
                        {
                            LimbImage.Name = txtName.Text;

                            RebuildAlphaTree();

                            IEnumerable<SpriteEditor_2017.classSprite_Limb.classSprite_Limb_Images> query = cLimb.lstImages.OrderBy(image => image.Name);
                            cLimb.lstImages = (List<SpriteEditor_2017.classSprite_Limb.classSprite_Limb_Images>)query.ToList<SpriteEditor_2017.classSprite_Limb.classSprite_Limb_Images>();

                            panelLimb_ImageController.instance.resetScrollingPanel();
                            panelLimb_ImageController.instance.pnlScrolling.PositionPanels();
                            int intImage_new_Index = cLimb.lstImages.IndexOf(LimbImage);
                            panelLimb_ImageController.instance.pnlScrolling.ScrollTo(intImage_new_Index);
                        }
                        else
                        {
                            txtName.Text = LimbImage.Name;
                        }
                        txtName.BackColor = Color.White;
                    }
                }
            }

            /// <summary>
            /// tests 
            /// </summary>
            /// <param name="strName"></param>
            /// <returns></returns>
            bool NameInListAlready(string strName)
            {
                classSprite_Limb.classSprite_Limb_Images cLimbImageIntree = (classSprite_Limb.classSprite_Limb_Images)Limb.cBT_LimbImages.Search(strName);
                if (cLimbImageIntree != null)
                {
                    MessageBox.Show("There is already an image with the name " + strName + ".\r\nLimb image names must be unique for that limb.");
                    return true;
                }
                return false ;
            }

            /// <summary>
            /// UI highlights changes made to the image's name in yellow until changes are saved when the user presses the ENTER key
            /// </summary>
            private void TxtName_TextChanged(object sender, System.EventArgs e)
            {
                txtName.BackColor = Color.Yellow;
            }

            /// <summary>
            /// places controls on this panel after the panel's size changed
            /// </summary>
            private void PanelImageDisplay_SizeChanged(object sender, System.EventArgs e)
            {
                placeObjects();
            }

            /// <summary>
            /// positions panel's controls after a size change
            /// </summary>
            void placeObjects()
            {
                lblName.Top
                    = txtName.Top
                    = 2;

                lblName.Left = 2;
                txtName.Left = lblName.Right;
                txtName.Width = Width - txtName.Left - 2;

                btnDelete.Left = Width - btnDelete.Width - 2;
                btnDelete.Top = Height - btnDelete.Height - 2;

                pic.Top = txtName.Bottom;
                pic.Left = 0;
                pic.Width = Width;
                pic.Height = btnDelete.Top - txtName.Bottom;
            }
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
        const string conHeading = "Limb Image Controller : ";
        const int conScrollingPanelContainerHeight_LessImageHeight = 150;
        classSprite_Limb _cLimb = null;
        /// <summary>
        /// limb whose images are to be drawn and edited
        /// </summary>
        public classSprite_Limb Limb
        {
            get { return _cLimb; }
            set
            {
                if (_cLimb != value)
                {
                    _cLimb = value;
                    resetScrollingPanel();
                    Heading.Text = conHeading + _cLimb.Name;
                }
            }
        }

        /// <summary>
        /// Vertical scrolling panel used to hold and display all of the selected limb's limbimages
        /// </summary>
        public panelScrolling_Vertical pnlScrolling = new panelScrolling_Vertical();
        public Button btnAdd = new Button();
        public Button btnOk = new Button();

        /// <summary>
        ///  instantiates panel using standard Header font
        /// </summary>
        public panelLimb_ImageController() { Init(fntStandard); }
        /// <summary>
        ///  instantiates panel using specified Header font
        /// </summary>
        /// <param name="fnt"></param>
        public panelLimb_ImageController(Font fnt) { Init(fnt); }

        /// <summary>
        /// initializes the panel's controls
        /// </summary>
        /// <param name="fnt"></param>
        void Init(Font fnt)
        {
            instance = this;

            Heading.Font = fnt;
            Heading.BackColor = Color.LightPink;
            BackColor = Color.White;
            BorderStyle = BorderStyle.Fixed3D;

            btnAdd.Text = "Add";
            btnAdd.AutoSize = true;
            btnAdd.Click += BtnAdd_Click;
            btnAdd.MouseWheel += _MouseWheel;
            pnlContainer.Controls.Add(btnAdd);

            btnOk.Text = "Ok";
            btnOk.AutoSize = true;
            btnOk.Click += BtnOk_Click;
            btnOk.MouseWheel += _MouseWheel;
            pnlContainer.Controls.Add(btnOk);

            pnlContainer.MouseWheel += _MouseWheel;
            pnlContainer.Controls.Add(pnlScrolling);

            setToolTip();

            // sets the panel's size, location and other parameters according to Format_Load() results loaded previously
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].size_Width,
                            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].size_Height);

            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].ExpansionDirection;

            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].bolIgnoreChanges = false;
            Heading.Text = "Limb Image Controller";


            SizeChanged += PanelLimb_ImageController_SizeChanged;
            LocationChanged += PanelLimb_ImageController_LocationChanged;
            Disposed += PanelLimb_ImageController_Disposed;

            BringToFront();
            placeObjects();
        }

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

            tt.SetToolTip(pnlScrolling, "Costumes this limb can have.");
            tt.SetToolTip(btnAdd, "adds a new limb image to this limb at the bottom of the list.");
            tt.SetToolTip(btnOk, "closes this window");
        }

        /// <summary>
        /// mousewheel function that controls all panel's controls's mousewheel events to scroll the Vertical Scrolling panel
        /// </summary>
        public void _MouseWheel(object sender, MouseEventArgs e)
        {
            ScrollEventType scEventType = e.Delta < 0
                                                  ? ScrollEventType.SmallIncrement
                                                  : ScrollEventType.SmallDecrement;
            ScrollEventArgs scrEventArgs = new ScrollEventArgs(scEventType, pnlScrolling.vsb.Value + e.Delta);
            pnlScrolling.Scroll(sender, scrEventArgs);
        }

        /// <summary>
        /// hides the panelLimb_ImageController
        /// </summary>
        private void BtnOk_Click(object sender, EventArgs e) { Hide(); }

        /// <summary>
        /// adds a new image panel to the list of limb's LimbImages with default value until user specifies the new image to be added to the selected limb
        /// </summary>
        private void BtnAdd_Click(object sender, EventArgs e)
        {
            Panel pnlScrollingContainer = new Panel();
            classSprite_CostumeInfo cCostume_Temp = formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo;

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

            string strNew_Name = getDefaultImageName();

            Font fnt = new Font("courier", 12, FontStyle.Regular);
            string strNew = "New limb image\r\nNot loaded";
            Size szNew = TextRenderer.MeasureText(strNew, fnt);
            Bitmap bmpNew = new Bitmap(szNew.Width, szNew.Height);

            using (Graphics g = Graphics.FromImage(bmpNew))
            {
                g.FillRectangle(Brushes.White, new RectangleF(classGraphics.ptZero, bmpNew.Size));
                g.DrawString(strNew, fnt, Brushes.Black, classGraphics.ptZero);
            }

            classSprite_Limb.classSprite_Limb_Images cLimbImage = _cLimb.ListImages_Add(strNew_Name, bmpNew);

            for (int intCostumeCounter = 0; intCostumeCounter < formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo.Count; intCostumeCounter++)
            {
                classSprite_CostumeInfo cCostume = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.lstCostumeInfo[intCostumeCounter];
                classSprite_Limb cLimb_Costume = (classSprite_Limb)cCostume.cBT_Limbs.Search(_cLimb.Name);
                if (cLimb_Costume == null)
                {
                    cLimb_Costume.lstImages.Add(_cLimb.lstImages[_cLimb.lstImages.Count - 1].Copy());
                }
            }

            formSpriteEditor_2017.instance.cSpriteData.cCostumeInfo = cCostume_Temp;

            /*
            panelImageDisplay pnlImageDisplay = new panelImageDisplay(ref _cLimb, ref cLimbImage);
            
            pnlScrollingContainer.Height = pnlImageDisplay.Height;

            pnlImageDisplay.Dock = DockStyle.Fill;

            pnlScrollingContainer.Controls.Add(pnlImageDisplay);
            pnlImageDisplay.pnlMyContainer = pnlScrollingContainer;

            pnlScrolling.AddPanel(ref pnlScrollingContainer);
            /*/
            resetScrollingPanel();
            Heading.Text = conHeading + _cLimb.Name;
            //*/

            pnlScrolling.PositionPanels();

            int intImage_new_Index = _cLimb.lstImages.IndexOf(cLimbImage);
            pnlScrolling.ScrollTo(intImage_new_Index);
        }

        /// <summary>
        /// creates a unique limbImage name
        /// </summary>
        /// <returns>a limb image name unique to thie specifeied</returns>
        string getDefaultImageName()
        {
            string strDefault = classSprite_Limb.conDefaultLimbImageName.ToLower();

            List<classSprite_Limb.classSprite_Limb_Images> lstDefaultNames = new List<classSprite_Limb.classSprite_Limb_Images>();

            for (int intImageCounter = 0; intImageCounter < _cLimb.lstImages.Count; intImageCounter++)
            {
                string strName = _cLimb.lstImages[intImageCounter].Name.ToLower();
                if (strName.Length >= strDefault.Length)
                {
                    if (string.Compare(strDefault, strName.Substring(0, strDefault.Length)) == 0)
                    {
                        lstDefaultNames.Add(_cLimb.lstImages[intImageCounter]);
                    }
                }
            }
            if (lstDefaultNames.Count > 0)
            {
                IEnumerable<classSprite_Limb.classSprite_Limb_Images> query = lstDefaultNames.OrderBy(data => data.Name);
                lstDefaultNames = (List<classSprite_Limb.classSprite_Limb_Images>)query.ToList<classSprite_Limb.classSprite_Limb_Images>();
                string strUsed_Suffixes = ".";
                for (int intCounter = 0; intCounter < lstDefaultNames.Count; intCounter++)
                {
                    string strSuffix = lstDefaultNames[intCounter].Name.Substring(classSprite_Limb.conDefaultLimbImageName.Length) + ".";
                    strUsed_Suffixes += strSuffix;
                }

                int intCount = 0;
                string strUnused_Suffix = "1";
                do
                {
                    intCount++;
                    strUnused_Suffix = intCount.ToString();
                } while (strUsed_Suffixes.Contains("." + strUnused_Suffix + "."));

                return classSprite_Limb.conDefaultLimbImageName + strUnused_Suffix;
            }
            else
                return classSprite_Limb.conDefaultLimbImageName;
        }

        /// <summary>
        /// records panel's Collapsed/ExpansionDirection state for formatting purposes
        /// </summary>
        private void PanelLimb_ImageController_Disposed(object sender, System.EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].Collapsed = Collapsed;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].ExpansionDirection = ExpansionDirection;
        }

        /// <summary>
        /// records panel's location after a location change for formatting purposes
        /// </summary>
        private void PanelLimb_ImageController_LocationChanged(object sender, System.EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].location_Y = Location.Y;
            }
        }

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void PanelLimb_ImageController_SizeChanged(object sender, System.EventArgs e)
        {

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

            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_ImageController].Collapsed = Collapsed;
            placeObjects();
        }

        /// <summary>
        /// repositions panels after a size change
        /// </summary>
        public void ScrollingPanel_Refresh()
        {
            pnlScrolling.PositionPanels();
        }

        /// <summary>
        /// reinitializes the image display scrolling panel with new images of the currently selected limb
        /// </summary>
        public void resetScrollingPanel()
        {
            pnlScrolling.clear();
            for (int intImageListCounter = 0; intImageListCounter < Limb.lstImages.Count; intImageListCounter++)
            {
                Panel pnlScrollingContainer = new Panel();

                classSprite_Limb.classSprite_Limb_Images cLimbImages = Limb.lstImages[intImageListCounter];
                panelImageDisplay pnlImageDisplay = new panelImageDisplay(ref _cLimb, ref cLimbImages);
                pnlScrollingContainer.Controls.Add(pnlImageDisplay);
                pnlImageDisplay.pnlMyContainer = pnlScrollingContainer;
                pnlScrollingContainer.Height = cLimbImages.bmpImages[0].Height + conScrollingPanelContainerHeight_LessImageHeight ;
                pnlScrolling.AddPanel(ref pnlScrollingContainer);
            }
            pnlScrolling.PositionPanels();
        }

        /// <summary>
        ///  places panels controls onto the screen
        /// </summary>
        void placeObjects()
        {
            btnAdd.Left = 2;
            btnAdd.Top = 2;

            btnOk.Top = pnlContainer.Height - btnOk.Height - 2;
            btnOk.Left = pnlContainer.Width - btnOk.Width - 2;

            pnlScrolling.Top = btnAdd.Bottom;
            pnlScrolling.Left = btnAdd.Left;
            pnlScrolling.Height = btnOk.Top - pnlScrolling.Top - 2;
            pnlScrolling.Width = pnlContainer.Width - 4;
        }
    }

    /// <summary>
    /// panel provides the user with a means to deattach a selected limb from its master and reattach it to a new limb to be selected
    /// </summary>
    public class panelLimb_Reattach : panelMoveable
    {
        public PictureBox picLimbToReattach = new PictureBox();
        public Label lblLimbToReattach = new Label();

        public PictureBox picMasterLimb_Current = new PictureBox();
        public Label lblMasterLimb_Current = new Label();

        public PictureBox picMasterLimb_New = new PictureBox();
        public Label lblMasterLimb_new = new Label();

        public ComboBox cmbMasterLimbs = new ComboBox();
        public Label[] lblText = new Label[6];
        /// <summary>
        /// identifies a string of labels used to write the UI instructions
        /// </summary>
        enum enuLabels { Limb_Reattach, Limb_ToReattach, From, Limb_MasterCurrent, To, Limb_MasterNew };

        public Button btnOk = new Button();
        public Button btnCancel = new Button();

        classSpriteData cSpriteData;
        classSprite_Limb cLimb;
        classSprite_Limb cLimb_Master_New = null;

        /// <summary>
        ///  initializes panelLimb_Reattach with standard font drawing the Header
        /// </summary>
        public panelLimb_Reattach() { Init(fntStandard); }
        /// <summary>
        /// initializes panelLimb_Reattach with a specified font drawing the panel's Header
        /// </summary>
        /// <param name="fnt"></param>
        public panelLimb_Reattach(Font fnt) { Init(fnt); }

        /// <summary>
        /// initializes the panelLimb_Reattach and all its controls
        /// </summary>
        /// <param name="fnt">font used to draw the panel's Header</param>
        void Init(Font fnt)
        {
            cSpriteData = formSpriteEditor_2017.instance.cSpriteData;
            Heading.Font = fnt;
            BackColor = Color.White;
            BorderStyle = BorderStyle.Fixed3D;

            pnlContainer.Controls.Add(picLimbToReattach);
            picLimbToReattach.Name = "picLimbToReattach";
            picLimbToReattach.BorderStyle = BorderStyle.Fixed3D;

            pnlContainer.Controls.Add(lblLimbToReattach);
            lblLimbToReattach.Name = "lblLimbToReattach";
            lblLimbToReattach.AutoSize = false;
            lblLimbToReattach.TextAlign = ContentAlignment.MiddleCenter;

            pnlContainer.Controls.Add(picMasterLimb_Current);
            picMasterLimb_Current.Name = "picMasterLimb_Current";
            picMasterLimb_Current.BorderStyle = picLimbToReattach.BorderStyle;

            pnlContainer.Controls.Add(lblMasterLimb_Current);
            lblMasterLimb_Current.Name = "lblMasterLimb_Current";
            lblMasterLimb_Current.AutoSize = false;
            lblMasterLimb_Current.TextAlign = ContentAlignment.MiddleLeft;

            pnlContainer.Controls.Add(picMasterLimb_New);
            picMasterLimb_New.Name = "picMasterLimb_New";
            picMasterLimb_New.BorderStyle = picLimbToReattach.BorderStyle;

            pnlContainer.Controls.Add(picMasterLimb_New);
            lblMasterLimb_new.Name = "lblMasterLimb_new";
            lblMasterLimb_new.AutoSize = false;
            lblMasterLimb_new.TextAlign = ContentAlignment.MiddleRight;

            pnlContainer.Controls.Add(cmbMasterLimbs);
            cmbMasterLimbs.Name = "cmbMasterLimbs";
            cmbMasterLimbs.SelectedIndexChanged += cmbMasterLimbs_SelectedIndexChanged;

            // initializes all the user instructions labels with their basic values 
            for (int intLabelCounter = 0; intLabelCounter < lblText.Length; intLabelCounter++)
            {
                lblText[intLabelCounter] = new Label();
                pnlContainer.Controls.Add(lblText[intLabelCounter]);
                lblText[intLabelCounter].AutoSize = true;
                lblText[intLabelCounter].BackColor = Color.White;
                lblText[intLabelCounter].Top = 0;
            }

            /////////////////////////////////////////////////////////////////////////////////////////////////
            //                          specifies font size and colors of similar labels
            /////////////////////////////////////////////////////////////////////////////////////////////////
            lblText[(int)enuLabels.Limb_Reattach].Font
                = lblText[(int)enuLabels.From].Font
                = lblText[(int)enuLabels.To].Font
                = new Font("Mongolian Baiti", 18, FontStyle.Regular);

            lblText[(int)enuLabels.Limb_Reattach].ForeColor
                = lblText[(int)enuLabels.From].ForeColor
                = lblText[(int)enuLabels.To].ForeColor
                = Color.DarkGray;

            lblText[(int)enuLabels.Limb_MasterCurrent].Font
                = lblText[(int)enuLabels.Limb_ToReattach].Font
                = lblText[(int)enuLabels.Limb_MasterNew].Font
                = new Font("Mongolian Baiti", 22, FontStyle.Italic);

            lblText[(int)enuLabels.Limb_MasterCurrent].ForeColor
                = lblText[(int)enuLabels.Limb_MasterCurrent].ForeColor
                = lblText[(int)enuLabels.Limb_MasterNew].ForeColor
                = Color.Black;

            lblText[(int)enuLabels.Limb_Reattach].Text = "Reattach Limb ";
            lblText[(int)enuLabels.From].Text = " from ";
            lblText[(int)enuLabels.To].Text = " to ";

            pnlContainer.Controls.Add(btnOk);
            btnOk.Name = "pnlLimb_Reattach_btnOk";
            btnOk.Text = "Ok";
            btnOk.AutoSize = true;
            btnOk.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            pnlContainer.Controls.Add(btnCancel);
            btnCancel.Name = "pnlLimb_Reattach_btnCancel";
            btnCancel.Text = "Cancel";
            btnCancel.AutoSize = true;
            btnCancel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            btnCancel.Click += BtnCancel_Click;

            setToolTip();
            init_Format();

            LocationChanged += PanelLimb_Reattach_LocationChanged;
            SizeChanged += PanelLimb_Reattach_SizeChanged;
            Disposed += PanelLimb_Reattach_Disposed;
        }

        public void init_Format()
        {  // initializes the panel's format according the values loaded by Format_Load() function previousy
            string strGeneric = "the currently selected limb can be detached from its master limb and reattached to a new master limb.";
            for (int intCounter = 0; intCounter < lblText.Length; intCounter++)
                formSpriteEditor_2017.instance.toolTip.SetToolTip(lblText[intCounter], strGeneric);

            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].Collapsed)
                Collapse();
            else
                Expand();
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].ExpansionDirection;
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolIgnoreChanges = false;
        }

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

            // pnlLimb_Reattach
            tt.SetToolTip(picLimbToReattach, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblLimbToReattach, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(picMasterLimb_Current, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblMasterLimb_Current, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(picMasterLimb_New, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblMasterLimb_new, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(cmbMasterLimbs, formSpriteEditor_2017.conDefaultToolTip);

            for (int intCounter = 0; intCounter < lblText.Length; intCounter++)
                tt.SetToolTip(lblText[intCounter], formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(btnOk, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(btnCancel, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// hides the panel after user clicks Cancel button
        /// </summary>
        private void BtnCancel_Click(object sender, EventArgs e)
        {
            Collapse();
            Hide();
        }

        /// <summary>
        /// reinitializes the controls necessary to ready the panel for the user to reattach the specified limb
        /// </summary>
        /// <param name="Limb">limb to be reattached</param>
        public void Limb_Reattach(ref classSprite_Limb Limb)
        {
            Expand();
            Show();

            cSpriteData.cAnimationData.cSprite = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite;
            cLimb = Limb;
            lblText[(int)enuLabels.Limb_ToReattach].Text = cLimb.Name;
            lblText[(int)enuLabels.Limb_MasterCurrent].Text = cLimb.Hinge.Limb_Master.Name;

            cmbMasterLimbs_Init();

            lblLimbToReattach.Text = cLimb.Name;
            lblMasterLimb_Current.Text = cLimb.Hinge.Limb_Master.Name;

            placeObjects();
            load_Pics();
        }


        List<classSprite_Limb> lstSlaveLimbs = new List<classSprite_Limb>();
        /// <summary>
        /// reinitializes the combobox containing the list of the sprite's limbs from which the user can select a new master limb for the currently selected limb
        /// </summary>
        void cmbMasterLimbs_Init()
        {
            cmbMasterLimbs.Items.Clear();
            lstSlaveLimbs.Clear();
            getSlaveLimbs(ref cLimb);


            List<classSprite_Limb> lstLimbs = new List<classSprite_Limb>();
            lstLimbs = (List<classSprite_Limb>)cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.ToList<classSprite_Limb>();

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

            for (int intLimbCounter = 0; intLimbCounter < lstLimbs.Count; intLimbCounter++)
            {
                if (lstLimbs[intLimbCounter] != cLimb
                    && !lstSlaveLimbs .Contains( lstLimbs[intLimbCounter] ))
                    cmbMasterLimbs.Items.Add(lstLimbs[intLimbCounter].Name);
            }
        }

        void getSlaveLimbs(ref classSprite_Limb cThisLimb)
        {
            lstSlaveLimbs.Add(cThisLimb);
            for (int intSlaveCounter = 0; intSlaveCounter < cThisLimb.lstHinge_Slaves.Count; intSlaveCounter++)
            {
                if (cThisLimb.lstHinge_Slaves[intSlaveCounter] != null)
                {
                    classSprite_Limb cSlaveLimb = cThisLimb.lstHinge_Slaves[intSlaveCounter].Limb_Slave;
                    getSlaveLimbs(ref cSlaveLimb);
                }
            }
        }


        /// <summary>
        /// resets the text identifying the user's new MasterLimb selection 
        /// </summary>
        void Txt_Update()
        {
            cLimb_Master_New = (classSprite_Limb)cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.cBT_Limbs.Search(cmbMasterLimbs.Text);
            lblText[(int)enuLabels.Limb_MasterNew].Text= (cLimb_Master_New != null
                                                                            ? cLimb_Master_New.Name
                                                                            : "???");
            lblMasterLimb_new.Text = cmbMasterLimbs.Text;
        }

        /// <summary>
        /// loads and draws the three images of the limbs involved in the LimbReattach operation
        /// </summary>
        void load_Pics()
        {
            load_PicLimb();
            load_PicMaster_Current();
            load_PicMaster_New();
        }

        /// <summary>
        /// loads the image of the limb which is being reattached into its given picturebox
        /// </summary>
        void load_PicLimb()
        {
            drawPic(ref picLimbToReattach, cLimb.lstImages[cLimb.intImageList_Index].bmpImages[0]);
        }

        /// <summary>
        /// loads the current MasterLimb's picture and draws it on its given picturebox
        /// </summary>
        void load_PicMaster_Current()
        {
            classSprite_Limb climbMaster = cLimb.Hinge.Limb_Master;

            drawPic(ref picMasterLimb_Current, climbMaster.lstImages[climbMaster.intImageList_Index].bmpImages[0]);
        }

        /// <summary>
        /// loads the new MasterLimb's picture and draws it on its given picturebox
        /// </summary>
        void load_PicMaster_New()
        {
            classSprite_Limb cLimb_Master_New = (classSprite_Limb)cSpriteData.cCostumeInfo.cBT_Limbs.Search(cmbMasterLimbs.Text);
            if (cLimb_Master_New != null)
                drawPic(ref picMasterLimb_New, cLimb_Master_New.lstImages[cLimb_Master_New.intImageList_Index].bmpImages[0]);
        }

        /// <summary>
        /// sizes to fit and draws the provided bitmap onto the provided picturebox
        /// </summary>
        /// <param name="pic">picturebox onto which the image is to be drawn</param>
        /// <param name="bmp">bitmap which is to be sized to fit and drawn</param>
        void drawPic(ref PictureBox pic, Bitmap bmp)
        {
            if (pic != null && bmp != null)
            {
                double dblBmpAspectRatio = (double)bmp.Height / (double)bmp.Width;
                double dblPicAspectRatio = (double)pic.Height / (double)pic.Width;
                double dblDrawSizeFactor = 1.0;
                if (dblBmpAspectRatio > dblPicAspectRatio)
                { // limit is height
                    dblDrawSizeFactor = (double)pic.Height / (double)bmp.Height;
                }
                else
                { // limit is width
                    dblDrawSizeFactor = (double)pic.Width / (double)bmp.Width;
                }

                Rectangle recSource = new Rectangle(classGraphics.ptZero, bmp.Size);
                Rectangle recDestion = new Rectangle(classGraphics.ptZero, new Size((int)((double)bmp.Width * dblDrawSizeFactor),
                                                                                    (int)((double)bmp.Height * dblDrawSizeFactor)));

                Bitmap bmpTemp = new Bitmap(pic.Width, pic.Height);
                using (Graphics g = Graphics.FromImage(bmpTemp))
                {
                    g.FillRectangle(Brushes.White, new Rectangle(classGraphics.ptZero, pic.Size));
                    g.DrawImage(bmp, recDestion, recSource, GraphicsUnit.Pixel);
                }
                pic.Image = bmpTemp;
            }
        }

        /// <summary>
        /// reacts to the user's latest selection change from the combobox listing sprite's limb choices for a new MasterLimb
        /// </summary>
        private void cmbMasterLimbs_SelectedIndexChanged(object sender, EventArgs e)
        {
            load_PicMaster_New();
            placeObjects();
        }

        /// <summary>
        /// records panel's Expansion direction for formatting purposes
        /// </summary>
        private void PanelLimb_Reattach_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].Collapsed =  Collapsed ; //not currently used as panel is hidden from user when not in use
        }

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void PanelLimb_Reattach_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolIgnoreChanges
                 && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// records location for formatting purposes
        /// </summary>
        private void PanelLimb_Reattach_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_Reattach].bolInit = true;
            }
        }

        /// <summary>
        /// places panel's controls onto the panel after a size change
        /// </summary>
        void placeObjects()
        {
            if (cSpriteData.cAnimationData.cSprite == null || cLimb == null) return;

            Txt_Update();
            for (int intLabelCounter = 1; intLabelCounter < lblText.Length; intLabelCounter++)
                lblText[intLabelCounter].Left = lblText[intLabelCounter - 1].Right;

            lblLimbToReattach.Width
                = lblMasterLimb_Current.Width
                = lblMasterLimb_new.Width
                = picLimbToReattach.Width
                = picMasterLimb_Current.Width
                = picMasterLimb_New.Width
                = cmbMasterLimbs.Width
                = (pnlContainer.Width - 2) / 3;

            Size sz = TextRenderer.MeasureText("Syntax Error Software", lblText[(int)enuLabels.Limb_ToReattach].Font);
            picMasterLimb_Current.Top
                = picLimbToReattach.Top
                = picMasterLimb_New.Top
                = (int)((double)sz.Height * 1.3);

            lblMasterLimb_Current.Top
                = lblLimbToReattach.Top
                = lblMasterLimb_new.Top
                = lblText[(int)enuLabels.Limb_Reattach].Bottom;

            picMasterLimb_Current.Height
                = picLimbToReattach.Height
                = picMasterLimb_New.Height
                = pnlContainer.Height - picMasterLimb_New.Top - cmbMasterLimbs.Height - btnCancel.Height;

            lblMasterLimb_Current.Left = 0;
            lblLimbToReattach.Left = lblMasterLimb_Current.Right + 1;
            lblMasterLimb_new.Left = lblLimbToReattach.Right + 1;


            picMasterLimb_Current.Left = 0;
            picLimbToReattach.Left = picMasterLimb_Current.Right + 1;
            picMasterLimb_New.Left = picLimbToReattach.Right + 1;



            cmbMasterLimbs.Left = picMasterLimb_New.Left;
            cmbMasterLimbs.Top = picMasterLimb_New.Bottom;


            btnOk.Top
                = btnCancel.Top
                = cmbMasterLimbs.Bottom;

            btnOk.Left = pnlContainer.Width - btnOk.Width;
            btnCancel.Left = btnOk.Left - btnCancel.Width;

            load_Pics();
        }
    }

    /// <summary>
    /// panel lets user copy limb values of several frames from one source animation to selected others
    /// </summary>
    public class panelLimb_CopyFrames : panelMoveable
    {
        /// <summary>
        /// identifies a string of labels used to write the UI instructions
        /// </summary>

        public Button btnOk = new Button();
        public Button btnCancel = new Button();
        public ListBox lbxLimbs = new ListBox();
        public ListBox lbxAnimations_Destination = new ListBox();
        public ListBox lbxAnimation_Source = new ListBox();
        public ListBox lbxFramesToCopy = new ListBox();
        
        public Label lblLimbs = new Label();
        public Label lblAnimations_Destination = new Label();
        public Label lblAnimation_Source = new Label();
        public Label lblFramesToCopy = new Label();

        public CheckBox chkKeepFrameIntegrity = new CheckBox();

        classSpriteData cSpriteData
        { 
        get { return formSpriteEditor_2017.instance.cSpriteData; }
        }


        public classAnimation Animation_Source
        {
            get
            {
                classAnimation cRetVal = null;

                if (lbxAnimation_Source.SelectedIndex >= 0)
                    cRetVal = cSpriteData.cAnimationData.cSprite.lstAnimations[lbxAnimation_Source.SelectedIndex];

                return cRetVal;
            }
        }

        public List<classAnimation> Animations_Destination
        {
            get
            {
                List<classAnimation> lstRetVal = new List<classAnimation>();

                for (int intAnimationCounter = 0; intAnimationCounter < cSpriteData.cAnimationData.cSprite.lstAnimations.Count; intAnimationCounter++)
                {
                    if (lbxAnimations_Destination.GetSelected(intAnimationCounter))
                        lstRetVal.Add(cSpriteData.cAnimationData.cSprite.lstAnimations[intAnimationCounter]);
                }

                return lstRetVal;
            }
        }

        public List<classAnimation_Frame> Frames_Source
        {
            get
            {
                if (lbxAnimation_Source.SelectedIndex < 0)
                    return new List<classAnimation_Frame>();
             
                List<classAnimation_Frame> lstRetVal = new List<classAnimation_Frame>();
                classAnimation cAnimationSource = cSpriteData.cAnimationData.cSprite.lstAnimations[lbxAnimation_Source.SelectedIndex];
                for (int intFrameCounter = 0; intFrameCounter < lbxFramesToCopy.Items.Count; intFrameCounter++)
                {
                    if (lbxFramesToCopy.GetSelected(intFrameCounter))
                        lstRetVal.Add(cAnimationSource.lstFrames[intFrameCounter]);
                }
                return lstRetVal;
            }
        }

        public List<classSprite_Limb> LimbsToCopy
        { 
            get 
            {
                List<classSprite_Limb> lstRetVal = new List<classSprite_Limb>();

                for (int intLimbCounter = 0; intLimbCounter < cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
                {
                    if (lbxLimbs.GetSelected(intLimbCounter))
                        lstRetVal.Add(cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter]);
                }

                return lstRetVal;
            }
        }

        bool bolKeepFrameIntegrity = false;
        public bool KeepFrameIntegrity
        { 
            get { return bolKeepFrameIntegrity; }
        }

        /// <summary>
        ///  initializes panelLimb_CopyFrames with standard font drawing the Header
        /// </summary>
        public panelLimb_CopyFrames(Font fnt) 
        {
            Heading.Font = fnt;
            Heading.BackColor = Color.BurlyWood;
            BackColor = Color.White;
            BorderStyle = BorderStyle.Fixed3D;

            pnlContainer.Controls.Add(btnOk);
            btnOk.Name = "pnlLimb_CopyFrames_btnOk";
            btnOk.Text = "Ok";
            btnOk.AutoSize = true;
            btnOk.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            pnlContainer.Controls.Add(btnCancel);
            btnCancel.Name = "pnlLimb_CopyFrames_btnCancel";
            btnCancel.Text = "Cancel";
            btnCancel.AutoSize = true;
            btnCancel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            btnCancel.Click += BtnCancel_Click;

            pnlContainer.Controls.Add(lbxLimbs);
            lbxLimbs.Name = "pnlLimb_CopyFrames_lbxLimbs";
            lbxLimbs.SelectionMode = SelectionMode.MultiSimple;

            pnlContainer.Controls.Add(lbxAnimations_Destination);
            lbxAnimations_Destination.Name = "pnlLimb_CopyFrames_lbxAnimations_Destination";
            lbxAnimations_Destination.SelectionMode = SelectionMode.MultiSimple;
            
            pnlContainer.Controls.Add(lbxAnimation_Source);
            lbxAnimation_Source.Name = "pnlLimb_CopyFrames_lbxAnimation_Source";
            lbxAnimation_Source.SelectedIndexChanged += LbxAnimation_Source_SelectedIndexChanged;
            
            pnlContainer.Controls.Add(lbxFramesToCopy);
            lbxFramesToCopy.Name = "pnlLimb_CopyFrames_lbxFramesToCopy";
            lbxFramesToCopy.SelectionMode = SelectionMode.MultiSimple;

            pnlContainer.Controls.Add(lblLimbs);
            lblLimbs.Name = "pnlLimb_CopyFrames_lblLimbs";
            lblLimbs.Text = "Limbs";

            pnlContainer.Controls.Add(lblAnimations_Destination);
            lblAnimations_Destination.Name = "pnlLimb_CopyFrames_lblAnimation_Destination";
            lblAnimations_Destination.Text = "Animations Destination";
            
            pnlContainer.Controls.Add(lblAnimation_Source);
            lblAnimation_Source.Name = "pnlLimb_CopyFrames_lblAnimation_Source";
            lblAnimation_Source.Text = "Animation Source";
            
            pnlContainer.Controls.Add(lblFramesToCopy);
            lblFramesToCopy.Name = "pnlLimb_CopyFrames_lblFramesToCopy";
            lblFramesToCopy.Text = "Frames to Copy";

            pnlContainer.Controls.Add(chkKeepFrameIntegrity);
            chkKeepFrameIntegrity.Name = "pnlLimb_CopyFrames_chkKeepFrameIntegrity";
            chkKeepFrameIntegrity.Text = "Keep Frame Integrity";
            chkKeepFrameIntegrity.Checked = bolKeepFrameIntegrity;
            chkKeepFrameIntegrity.AutoSize = true;
            chkKeepFrameIntegrity.Click += ChkKeepFrameIntegrity_Click;

            lblLimbs.AutoSize
                = lblAnimations_Destination.AutoSize
                = lblAnimation_Source.AutoSize
                = lblFramesToCopy.AutoSize
                = true;

            setToolTip();
            init_Format();

            LocationChanged += PanelLimb_CopyFrames_LocationChanged;
            SizeChanged += PanelLimb_CopyFrames_SizeChanged;
            Disposed += PanelLimb_CopyFrames_Disposed;
            VisibleChanged += PanelLimb_CopyFrames_VisibleChanged;
        }

        public void init_Format()
        {  // initializes the panel's format according the values loaded by Format_Load() function previousy
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].Collapsed)
                Collapse();
            else
                Expand();
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].ExpansionDirection;
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolIgnoreChanges = false;
        }

        private void ChkKeepFrameIntegrity_Click(object sender, EventArgs e)
        {
            bolKeepFrameIntegrity = chkKeepFrameIntegrity.Checked;
        }

        private void PanelLimb_CopyFrames_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible)
            {
                buildControls();
                placeObjects();
            }
        }

        private void LbxAnimation_Source_SelectedIndexChanged(object sender, EventArgs e)
        {
            buildFramesToCopy();
        }

        void buildControls()
        {
            lbxAnimations_Destination.Items.Clear();
            lbxAnimation_Source.Items.Clear();
            
            for (int intAnimationCounter = 0; intAnimationCounter < cSpriteData.cAnimationData.cSprite.lstAnimations.Count; intAnimationCounter++)
            {
                lbxAnimations_Destination.Items.Add(cSpriteData.cAnimationData.cSprite.lstAnimations[intAnimationCounter].Name);
                lbxAnimation_Source.Items.Add(cSpriteData.cAnimationData.cSprite.lstAnimations[intAnimationCounter].Name);
            }
            ContextMenu cMnuAnimationDestination = new ContextMenu();
            MenuItem mnuAnimationDestination_mnuSelectAll_click = new MenuItem("Select All", mnuSelectAll_click);
            cMnuAnimationDestination.MenuItems.Add(mnuAnimationDestination_mnuSelectAll_click);
            mnuAnimationDestination_mnuSelectAll_click.Tag = (object)lbxAnimations_Destination;
            MenuItem mnuAnimationDestination_mnuUnselectAll_click = new MenuItem("Unselect All", mnuUnselectAll_click);
            cMnuAnimationDestination.MenuItems.Add(mnuAnimationDestination_mnuUnselectAll_click);
            mnuAnimationDestination_mnuUnselectAll_click.Tag = (object)lbxAnimations_Destination;
            lbxAnimations_Destination.ContextMenu = cMnuAnimationDestination;

            // lbxLimbs
            lbxLimbs.Items.Clear();
            for (int intLimbCounter = 0; intLimbCounter < cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
            {
                lbxLimbs.Items.Add(cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter].Name);
            }
            ContextMenu cMnuLimb = new ContextMenu();
            MenuItem mnuLimb_SelectAll = new MenuItem("Select All", mnuSelectAll_click);
            cMnuLimb.MenuItems.Add(mnuLimb_SelectAll);
            mnuLimb_SelectAll.Tag = (object)lbxLimbs;
            MenuItem mnuLimb_UnselectAll = new MenuItem("Unselect All", mnuUnselectAll_click);
            cMnuLimb.MenuItems.Add(mnuLimb_UnselectAll);
            mnuLimb_UnselectAll.Tag = (object)lbxLimbs;
            lbxLimbs.ContextMenu = cMnuLimb;
            cMnuLimb.Tag = (object)lbxLimbs;

            ContextMenu cMnuFramesToCopy = new ContextMenu();
            MenuItem mnuFramesToCopy_SelectAll = new MenuItem("Select All", mnuSelectAll_click);
            cMnuFramesToCopy.MenuItems.Add(mnuFramesToCopy_SelectAll);
            mnuFramesToCopy_SelectAll.Tag = (object)lbxFramesToCopy;
            MenuItem mnuFramesToCopy_UnselectAll = new MenuItem("Unselect All", mnuUnselectAll_click);
            cMnuFramesToCopy.MenuItems.Add(mnuFramesToCopy_UnselectAll);
            mnuFramesToCopy_UnselectAll.Tag = (object)lbxFramesToCopy;
            lbxFramesToCopy.ContextMenu = cMnuFramesToCopy;
            cMnuFramesToCopy.Tag = (object)lbxFramesToCopy;
        }

        void mnuSelectAll_click(object sender, EventArgs e)
        {
            MenuItem mnuSender = (MenuItem)sender;
            ListBox lbxSender = (ListBox)mnuSender.Tag;

            for (int intCounter = 0; intCounter < lbxSender.Items.Count; intCounter++)
                lbxSender.SetSelected(intCounter, true);
        }

        void mnuUnselectAll_click(object sender, EventArgs e)
        {
            MenuItem mnuSender = (MenuItem)sender;
            ListBox lbxSender = (ListBox)mnuSender.Tag;
            for (int intCounter = 0; intCounter < lbxSender.Items.Count; intCounter++)
                lbxSender.SetSelected(intCounter, false);
        }
        void buildFramesToCopy()
        {
            lbxFramesToCopy.Items.Clear();
            int intWidth = 0;

            classAnimation cAnimationSource = Animation_Source;
            for (int intFrameCounter = 0; intFrameCounter < cAnimationSource.lstFrames.Count; intFrameCounter++)
            {
                lbxFramesToCopy.Items.Add(intFrameCounter.ToString());
                int intWidth_New = TextRenderer.MeasureText(intFrameCounter.ToString(), lbxFramesToCopy.Font).Width;
                if (intWidth_New > intWidth)
                    intWidth = intWidth_New;
            }
            lbxFramesToCopy.Width = intWidth + 10;
        }


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

            // pnlLimb_CopyFrames
            tt.SetToolTip(btnOk, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(btnCancel, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lbxLimbs, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbxAnimations_Destination, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbxAnimation_Source, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lbxFramesToCopy, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblLimbs, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblAnimations_Destination, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblAnimation_Source, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblFramesToCopy, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkKeepFrameIntegrity, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// hides the panel after user clicks Cancel button
        /// </summary>
        private void BtnCancel_Click(object sender, EventArgs e)
        {
            Collapse();
            Hide();
        }
     
        /// <summary>
        /// records panel's Expansion direction for formatting purposes
        /// </summary>
        private void PanelLimb_CopyFrames_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].Collapsed = Collapsed; //not currently used as panel is hidden from user when not in use
        }

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void PanelLimb_CopyFrames_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolIgnoreChanges
                 && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// records location for formatting purposes
        /// </summary>
        private void PanelLimb_CopyFrames_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_CopyFrames].bolInit = true;
            }
        }

        /// <summary>
        /// places panel's controls onto the panel after a size change
        /// </summary>
        void placeObjects()
        {
            if (cSpriteData.cAnimationData.cSprite == null ) return;
            int intGap = 5;
            
            lbxAnimations_Destination.Width
                = lbxAnimation_Source.Width
                = lbxLimbs.Width
                = (pnlContainer.Width - 2*intGap - lbxFramesToCopy.Width) / 3;

            lblAnimation_Source.Top
                = lblAnimations_Destination.Top
                = lblLimbs.Top
                = lblFramesToCopy.Top
                = intGap;

            lbxAnimation_Source.Top
                = lbxAnimations_Destination.Top
                = lbxLimbs.Top
                = lbxFramesToCopy.Top
                = lblAnimation_Source.Bottom;

            lbxAnimation_Source.Height
                = lbxAnimations_Destination.Height
                = lbxLimbs.Height
                = lbxFramesToCopy.Height
                = pnlContainer.Height - intGap * 2 - btnCancel.Height - lbxAnimation_Source.Top;

            lblAnimation_Source.Left
                = lbxAnimation_Source.Left
                = intGap;

            lblAnimations_Destination.Left
                = lbxAnimations_Destination.Left
                = lbxAnimation_Source.Right;

            lblLimbs.Left
                = lbxLimbs.Left
                = lbxAnimations_Destination.Right;

            lbxFramesToCopy.Left = lbxLimbs.Right;

            btnOk.Top
                = btnCancel.Top
                = chkKeepFrameIntegrity.Top 
                = pnlContainer.Height - btnOk.Height - 5;

            btnOk.Left = pnlContainer.Width - btnOk.Width;
            btnCancel.Left = btnOk.Left - btnCancel.Width;
            chkKeepFrameIntegrity.Left = intGap;
        }
    }

    /// <summary>
    /// panel lets user generate multiple frame values for specified limbs into existing frames
    /// </summary>
    public class panelLimb_SetAnimation : panelMoveable
    {
        /// <summary>
        /// identifies a string of labels used to write the UI instructions
        /// </summary>

        public Button btnOk = new Button();
        public Button btnCancel = new Button();
        public ComboBox cmbAnimations = new ComboBox();
        public Label lblAnimations = new Label();

        public ListBox lbxLimbs = new ListBox();
        public NumericUpDown nudFrame_Start= new NumericUpDown();
        public NumericUpDown nudFrame_End = new NumericUpDown();

        public Label lblFrame_Start = new Label();
        public Label lblFrame_End = new Label();
        public Label lblLimbs = new Label();
        
        classSpriteData cSpriteData
        {
            get { return formSpriteEditor_2017.instance.cSpriteData; }
        }

        classAnimation cAnimation = null;
        public classAnimation Animation
        { 
        get { return cAnimation; }
        }

        public List<classSprite_Limb> Limbs
        {
            get
            {
                List<classSprite_Limb> lstRetVal = new List<classSprite_Limb>();

                for (int intLimbCounter = 0; intLimbCounter < cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
                {
                    if (lbxLimbs.GetSelected(intLimbCounter))
                        lstRetVal.Add(cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter]);
                }

                return lstRetVal;
            }
        }

        int intFrame_Start = 0;
        public int FrameStart
        {
            get { return intFrame_Start; }
        }

        int intFrame_End = 0;
        public int FrameEnd
        {
            get { return intFrame_End; }
        }

        /// <summary>
        ///  initializes panelLimb_SetAnimation with standard font drawing the Header
        /// </summary>
        public panelLimb_SetAnimation(Font fnt)
        {
            Heading.Font = fnt;
            Heading.BackColor = Color.DarkSeaGreen;
            BackColor = Color.White;
            BorderStyle = BorderStyle.Fixed3D;

            pnlContainer.Controls.Add(btnOk);
            btnOk.Name = "pnlLimb_SetAnimation_btnOk";
            btnOk.Text = "Ok";
            btnOk.AutoSize = true;
            btnOk.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            pnlContainer.Controls.Add(btnCancel);
            btnCancel.Name = "pnlLimb_SetAnimation_btnCancel";
            btnCancel.Text = "Cancel";
            btnCancel.AutoSize = true;
            btnCancel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            btnCancel.Click += BtnCancel_Click;

            // lbxLimbs
            {
                pnlContainer.Controls.Add(lbxLimbs);
                lbxLimbs.Name = "pnlLimb_SetAnimation_lbxLimbs";
                lbxLimbs.SelectionMode = SelectionMode.MultiSimple;

                ContextMenu cMnuLimb = new ContextMenu();
                MenuItem mnuLimb_SelectAll = new MenuItem("Select All", mnuSelectAll_click);
                cMnuLimb.MenuItems.Add(mnuLimb_SelectAll);
                mnuLimb_SelectAll.Tag = (object)lbxLimbs;
                MenuItem mnuLimb_UnselectAll = new MenuItem("Unselect All", mnuUnselectAll_click);
                cMnuLimb.MenuItems.Add(mnuLimb_UnselectAll);
                mnuLimb_UnselectAll.Tag = (object)lbxLimbs;
                lbxLimbs.ContextMenu = cMnuLimb;
                cMnuLimb.Tag = (object)lbxLimbs;
            }

            pnlContainer.Controls.Add(cmbAnimations);
            cmbAnimations.Name = "pnlLimb_SetAnimation_cmbAnimations";
            cmbAnimations.SelectedIndexChanged += CmbAnimations_SelectedIndexChanged;

            pnlContainer.Controls.Add(lblAnimations);
            lblAnimations.AutoSize = true;
            lblAnimations.Name = "pnlLimb_SetAnimation_lblAnimations";
            lblAnimations.Text = "Animations";

            pnlContainer.Controls.Add(nudFrame_Start);
            nudFrame_Start.Name = "pnlLimb_SetAnimation_nudFrameStart";
            nudFrame_Start.Minimum = 0;
            nudFrame_Start.MouseWheel += NudFrame_MouseWheel;
            nudFrame_Start.ValueChanged += NudFrame_Start_ValueChanged;

            pnlContainer.Controls.Add(lblFrame_Start);
            lblFrame_Start.Text = "Frame Start";
            lblFrame_Start.Name = "pnlLimb_SetAnimation_lblFrame_Start";
            lblFrame_Start.AutoSize = true;

            pnlContainer.Controls.Add(nudFrame_End);
            nudFrame_End.Name = "pnlLimb_SetAnimation_nudFrameEnd";
            nudFrame_End.Minimum = 0;
            nudFrame_End.MouseWheel += NudFrame_MouseWheel;
            nudFrame_End.ValueChanged += NudFrame_End_ValueChanged;

            pnlContainer.Controls.Add(lblFrame_End);
            lblFrame_End.Name = "pnlLimb_SetAnimation_lblFrame_End";
            lblFrame_End.Text = "Frame End";
            lblFrame_End.AutoSize = true;

            pnlContainer.Controls.Add(lblLimbs);
            lblLimbs.Name = "pnlLimb_SetAnimation_lblLimbs";
            lblLimbs.Text = "Limbs";

            setToolTip();
            init_Format();

            LocationChanged += PanelLimb_SetAnimation_LocationChanged;
            SizeChanged += PanelLimb_SetAnimation_SizeChanged;
            Disposed += PanelLimb_SetAnimation_Disposed;
            VisibleChanged += PanelLimb_SetAnimation_VisibleChanged;
        }

        public void init_Format()
        { // initializes the panel's format according the values loaded by Format_Load() function previousy
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].Collapsed)
                Collapse();
            else
                Expand();
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].ExpansionDirection;
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].location_Y);
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolIgnoreChanges = false;
        }

        private void NudFrame_MouseWheel(object sender, MouseEventArgs e)
        {
            HandledMouseEventArgs handledArgs = e as HandledMouseEventArgs;
            handledArgs.Handled = true;

            NumericUpDown nudSender = (NumericUpDown)sender;
            int intNewValue = (int)nudSender.Value + (int)(handledArgs.Delta > 0 ? 1 : -1);
            if (intNewValue > nudSender.Maximum)
                nudSender.Value = nudSender.Maximum;
            else if (intNewValue < nudSender.Minimum)
                nudSender.Value = nudSender.Minimum;
            else
                nudSender.Value += (handledArgs.Delta > 0) ? 1 : -1;
        }

        private void CmbAnimations_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbAnimations.SelectedIndex >= 0 && cmbAnimations.SelectedIndex < cSpriteData.cAnimationData.cSprite.lstAnimations.Count)
                cAnimation = cSpriteData.cAnimationData.cSprite.lstAnimations[cmbAnimations.SelectedIndex];
            else
                cAnimation = null;
        }

        private void NudFrame_End_ValueChanged(object sender, EventArgs e)
        {
            intFrame_End = (int)nudFrame_End.Value;
        }

        private void NudFrame_Start_ValueChanged(object sender, EventArgs e)
        {
            intFrame_Start = (int)nudFrame_Start.Value;
        }

        private void PanelLimb_SetAnimation_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible)
            {
                SetObjects();
                placeObjects();
            }
        }

        public void SetObjects()
        {
            lbxLimbs.Items.Clear();

            for (int intLimbCounter = 0; intLimbCounter < cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
            {
                lbxLimbs.Items.Add(cSpriteData.cAnimationData.cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter].Name);
            }
            
            nudFrame_End.Maximum = cSpriteData.cAnimationData.cAnimation.lstFrames.Count - 1;
            nudFrame_Start.Maximum = cSpriteData.cAnimationData.cAnimation.lstFrames.Count - 1;

            cmbAnimations.Items.Clear();
            for (int intAnimationCounter = 0; intAnimationCounter < cSpriteData.cAnimationData.cSprite.lstAnimations.Count; intAnimationCounter++)
                cmbAnimations.Items.Add(cSpriteData.cAnimationData.cSprite.lstAnimations[intAnimationCounter].Name);
            try
            {
                cmbAnimations.SelectedIndex = cSpriteData.cAnimationData.cSprite.lstAnimations.IndexOf(cSpriteData.cAnimationData.cAnimation);
            }
            catch (Exception)
            {
            }
            
        }


        void mnuSelectAll_click(object sender, EventArgs e)
        {
            MenuItem mnuSender = (MenuItem)sender;
            ListBox lbxSender = (ListBox)mnuSender.Tag;

            for (int intCounter = 0; intCounter < lbxSender.Items.Count; intCounter++)
                lbxSender.SetSelected(intCounter, true);
        }

        void mnuUnselectAll_click(object sender, EventArgs e)
        {
            MenuItem mnuSender = (MenuItem)sender;
            ListBox lbxSender = (ListBox)mnuSender.Tag;
            for (int intCounter = 0; intCounter < lbxSender.Items.Count; intCounter++)
                lbxSender.SetSelected(intCounter, false);
        }

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

            // pnlLimb_SetAnimation
            tt.SetToolTip(btnOk, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(btnCancel, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lbxLimbs, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblLimbs, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblFrame_Start, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(nudFrame_Start, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(lblFrame_End, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(nudFrame_End, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblAnimations, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(cmbAnimations, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// hides the panel after user clicks Cancel button
        /// </summary>
        private void BtnCancel_Click(object sender, EventArgs e)
        {
            Collapse();
            Hide();
        }

        /// <summary>
        /// records panel's Expansion direction for formatting purposes
        /// </summary>
        private void PanelLimb_SetAnimation_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].Collapsed = Collapsed; //not currently used as panel is hidden from user when not in use
        }

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void PanelLimb_SetAnimation_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolIgnoreChanges
                 && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// records location for formatting purposes
        /// </summary>
        private void PanelLimb_SetAnimation_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Limb_SetAnimation].bolInit = true;
            }
        }

        /// <summary>
        /// places panel's controls onto the panel after a size change
        /// </summary>
        void placeObjects()
        {
            if (cSpriteData.cAnimationData.cSprite == null) return;
            int intGap = 5;

            lblFrame_Start.Top
                = lblFrame_End.Top
                = intGap;

            nudFrame_Start.Top
                = nudFrame_End.Top
                = lblFrame_Start.Bottom;

            nudFrame_Start.Width
                = nudFrame_End.Width
                = (pnlContainer.Width - 2 * intGap) / 2;

            lblFrame_Start.Left
                = nudFrame_Start.Left
                = intGap;

            lblFrame_End.Left
                = nudFrame_End.Left
                = nudFrame_Start.Right;

            lblLimbs.Top = nudFrame_End.Bottom;
            lbxLimbs.Top = lblLimbs.Bottom;
            lbxLimbs.Width = pnlContainer.Width - 2 * intGap;
            lblLimbs.Left
                = lbxLimbs.Left
                = intGap;
            lbxLimbs.Height = pnlContainer.Height - btnCancel.Height - intGap - lbxLimbs.Top;


            cmbAnimations.Width = pnlContainer.Width / 2;
            cmbAnimations.Top 
                = lblAnimations.Top 
                = lblLimbs.Top;
            cmbAnimations.Left = pnlContainer.Width - intGap - cmbAnimations.Width;
            lblAnimations.Left = cmbAnimations.Left - lblAnimations.Width;

            btnOk.Left = pnlContainer.Width - btnOk.Width;
            btnCancel.Left = btnOk.Left - btnCancel.Width;
            btnOk.Top
                = btnCancel.Top
                = pnlContainer.Height - intGap - btnOk.Height;
        }
    }


    /// <summary>
    /// allows the user to enter a single line of text
    /// </summary>
    public class panelMessenger : panelMoveable
    {
        public TextBox txtUserInput = new TextBox();
        public TextBox txtText = new TextBox();

        /// <summary>
        /// type of calls made by the calling formSpriteEditor_2017 when it asks the user for input - needed by calling form to decide how to handle user's response
        /// </summary>
        public enum enuMessage
        {
            Sprite_New_Name,
            Limb_New_Name,
            Limb_Rename,
            Hinge_New_Name,
            Animation_New_Name,
            Resize,
            Animation_Rename,
            Costume_New,
            Costume_Rename
        };

        enuMessage eMessage = enuMessage.Sprite_New_Name;
        public enuMessage Message
        {
            get { return eMessage; }
        }

        /// <summary>
        /// initializes panelMessenger with standard font
        /// </summary>
        public panelMessenger() { Init(panelMoveable.fntStandard); }

        /// <summary>
        /// initializes panelMessenger with specified font
        /// </summary>
        /// <param name="fnt">font used to draw panel's Header</param>
        public panelMessenger(Font fnt) { Init(fnt); }

        /// <summary>
        /// initializes the controls on the panel
        /// </summary>
        /// <param name="fnt">font used to draw the Header</param>
        void Init(Font fnt)
        {
            pnlContainer.Controls.Add(txtUserInput);
            pnlContainer.Controls.Add(txtText);
            Text = "get Name";
            txtText.Multiline = true;
            txtText.Name = "txtText";
            txtText.Font = new Font("New Courier", 18, FontStyle.Regular);


            txtUserInput.Name = "txtUserInput";
                txtUserInput.Font = txtText.Font;

            setToolTip();

            init_Format();

            SizeChanged += panelMessenger_SizeChanged;
            LocationChanged += PanelMessenger_LocationChanged;
            txtUserInput.KeyPress += TxtUserInput_KeyPress;
            LostFocus += panelMessenger_LostFocus;
            Disposed += PanelMessenger_Disposed;
        }

        public void init_Format()
        { // initializes the panel with format data loaded by Format_Load() previously
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolIgnoreChanges = true;
            Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].size_Width,
                               formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].size_Height);
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].Collapsed)
                Collapse();
            else
                Expand();
            Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].location_X,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].location_Y);
            ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolIgnoreChanges = false;
        }

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

            // pnlMessenger
            tt.SetToolTip(txtUserInput, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtText, formSpriteEditor_2017.conDefaultToolTip);
        }

        /// <summary>
        /// function manages the user input to ensure final user response conforms to make a viable limb, sprite or animation name that can be searched by the classAlphaNumTree
        /// </summary>
        private void TxtUserInput_KeyPress(object sender, KeyPressEventArgs e)
        {
            string strTest =  eMessage == enuMessage.Resize 
                                        ? "0123456789"
                                        : classSprite_Limb.ValidLimbNameChar;
        

            if (!strTest.Contains(char.ToUpper(e.KeyChar)))
            {
                if (e.KeyChar != '\b')
                    e.Handled = true;
                if (e.KeyChar == '\r')
                {
                    Hide();
                    Object objText = (object)txtUserInput;
                    KeyEventArgs eTxt = new KeyEventArgs(Keys.Enter);

                    _KeyEventHandler(objText, eTxt);

                }

                else if (e.KeyChar == '\u001b') // escape
                {
                    Hide();
                }
            }

        }

        /// <summary>
        /// records panel's ExpansionDirection/Collapsed states for formatting purposes
        /// </summary>
        private void PanelMessenger_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].ExpansionDirection = ExpansionDirection;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].Collapsed = Collapsed;
        }

        /// <summary>
        /// records panel's location for formatting purposes
        /// </summary>
        private void PanelMessenger_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolInit = true;
            }
        }

        /// <summary>
        /// records panel's size for formatting purposes
        /// </summary>
        private void panelMessenger_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolIgnoreChanges
                     && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Messenger].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// returns focus to the txUserINput textbox when it is lost while panel is still visible
        /// </summary>
        private void panelMessenger_LostFocus(object sender, EventArgs e)
        {
            if (Visible)
            {
                txtUserInput.Focus();
            }
        }

        KeyEventHandler _KeyEventHandler = null;
        /// <summary>
        /// launches panelMessenger with specified parameters that do not include a suggested txtUserInput value
        /// </summary>
        /// <param name="strHeading">message to be printed in the panel's heading</param>
        /// <param name="strText">instruction message for the user's guidance</param>
        /// <param name="KeyEventHandler">function to be called and handled by calling form when user is finished entering new user input</param>
        /// <param name="message">type of user input the calling function is expecting</param>
        public void getName(string strHeading, string strText, KeyEventHandler KeyEventHandler, enuMessage message)
        {
            getName(strHeading, strText, "", KeyEventHandler, message);
        }

        /// <summary>
        /// launches panelMessenger with specified text for user's guidance
        /// </summary>
        /// <param name="strHeading">text printed in the panel's Header</param>
        /// <param name="strText">instructions for the user</param>
        /// <param name="strSuggestedUserInput">text automatically added to the user input textbox as a suggested viable input</param>
        /// <param name="KeyEventHandler">function that panelMessenger calls to reply to the calling form that the user has entered a response</param>
        /// <param name="message">type of input the calling function expects to handle once the user's input is entered</param>
        public void getName(string strHeading, string strText, string strSuggestedUserInput, KeyEventHandler KeyEventHandler, enuMessage message)
        {
            _KeyEventHandler = KeyEventHandler;
            Heading.Text = strHeading;
            txtText.Text = strText;
            txtUserInput.Text = strSuggestedUserInput;
            eMessage = message;
            Location = new Point((formSpriteEditor_2017.instance.Width - Width) / 2, (formSpriteEditor_2017.instance.Height - Height) / 2);
            BringToFront();
            Expand();
            placeObjects();
            Show();
            txtUserInput.Focus();
        }

        /// <summary>
        /// places panel's controls in the panel after a size change
        /// </summary>
        void placeObjects()
        {
            txtText.Location = new Point(0, 0);
            txtText.Width = pnlContainer.Width;
            txtText.Height = pnlContainer.Height - txtUserInput.Height - txtText.Top;
            txtUserInput.BringToFront();
            txtUserInput.Location = new Point(txtText.Left, txtText.Bottom);
            txtUserInput.Width = txtText.Width;
        }
    }

    /// <summary>
    /// contains all the controls that aid editing but do not relate directly to changing the values of the sprite or its components
    /// </summary>
    public class panelOptions : panelMoveable
    {
        /// <summary>
        /// public static variable that points to the only instance of this panel and can be reached from anywhere in the project
        /// </summary>
        public static panelOptions instance;
        public Label lblOptions_Magnitude_StepSize = new Label();
        public TextBox txtOptions_Magnitude_StepSize = new TextBox();

        public Label lblOptions_Radians_StepSize = new Label();
        public TextBox txtOptions_Radians_StepSize = new TextBox();

        public Label lblOptions_DrawAngle = new Label();
        public TextBox txtOptions_DrawAngle = new TextBox();

        public Label lblFocusController_StepSize = new Label();
        public TextBox txtFocusController_StepSize = new TextBox();

        public Label lblTimerDelay = new Label();
        public TextBox txtTimerDelay = new TextBox();

        Timer tmrShowLimbPositions_Hide = new Timer();

        public CheckBox chkShow_LimbNames = new CheckBox();
        public CheckBox chkShow_LimbPositions = new CheckBox();
        public CheckedListBox clbShow_LimbPositions = new CheckedListBox();
        public CheckBox chkShow_LimbCenters = new CheckBox();
        public CheckBox chkShow_FocusController = new CheckBox();
        public CheckBox chkShow_Frame = new CheckBox();
        public CheckBox chkShow_ToolTips = new CheckBox();

        /// <summary>
        /// true if tmrAnimation is enabled and UseRAMCache checkbox is checked
        /// </summary>
        public bool UseRAMCache
        {
            get { return formSpriteEditor_2017.instance.tmrAnimation.Enabled && chkUseRAMCache.Checked; }
        }
        public CheckBox chkUseRAMCache = new CheckBox();

        public groupBox grbRotatedLimbImage = new groupBox();
        public List<RadioButton> lstLimbImageRotationSelection = new List<RadioButton>();


        /// <summary>
        /// instantiates the panelOptions with standard font to draw Header
        /// </summary>
        public panelOptions() { Init(panelMoveable.fntStandard); }
  
        /// <summary>
        /// instantiates the panelOptions with specified font to draw Header
        /// </summary>
        /// <param name="fnt">font used to draw Header</param>
        public panelOptions(Font fnt) { Init(fnt); }

        /// <summary>
        /// initializes the panel's controls and formatting
        /// </summary>
        /// <param name="fnt">font used to draw panel's Header</param>
        void Init(Font fnt)
        {
            instance = this;
            tmrShowLimbPositions_Hide.Interval = 200;
            tmrShowLimbPositions_Hide.Tick += TmrShowLimbPositions_Hide_Tick;

            Heading.Font = fnt;
            Heading.BackColor = Color.Black;
            Heading.ForeColor = Color.Beige;
            pnlContainer.BackColor = Color.Black;
            pnlContainer.ForeColor = Color.White;

            pnlContainer.Controls.Add(lblFocusController_StepSize);
            lblFocusController_StepSize.Text = "Focus Controller StepSize";
            lblFocusController_StepSize.Name = "lblFocusController_StepSize";
            pnlContainer.Controls.Add(txtFocusController_StepSize);

            txtFocusController_StepSize.Name = "txtFocusController_StepSize";
            txtFocusController_StepSize.Text = formSpriteEditor_2017.intFocusController_StepSize.ToString();
            txtFocusController_StepSize.KeyDown += formSpriteEditor_2017.instance.txt_KeyDown_NumericOnly;
            txtFocusController_StepSize.TextChanged += TxtFocusController_StepSize_TextChanged;
            txtFocusController_StepSize.MouseWheel += formSpriteEditor_2017.instance.Txt_Magnitude_MouseWheel;

            pnlContainer.Controls.Add(lblOptions_Magnitude_StepSize);
            lblOptions_Magnitude_StepSize.Name = "lblOptions_Magnitude_StepSize";
            lblOptions_Magnitude_StepSize.Text = "Magnitude Step Size";

            pnlContainer.Controls.Add(txtOptions_Magnitude_StepSize);
            txtOptions_Magnitude_StepSize.Name = "txtOptions_Magnitude_StepSize";
            txtOptions_Magnitude_StepSize.KeyDown += formSpriteEditor_2017.instance.txt_KeyDown_NumericOnly;
            txtOptions_Magnitude_StepSize.TextChanged += TxtOptions_Magnitude_StepSize_TextChanged;
            txtOptions_Magnitude_StepSize.MouseWheel += formSpriteEditor_2017.instance.Txt_Magnitude_MouseWheel;

            pnlContainer.Controls.Add(lblOptions_Radians_StepSize);
            lblOptions_Radians_StepSize.Name = "lblOptions_Radians_StepSize";
            lblOptions_Radians_StepSize.Text = "Radians Step Size";

            pnlContainer.Controls.Add(txtOptions_Radians_StepSize);
            txtOptions_Radians_StepSize.Name = "txtOptions_Radians_StepSize";
            txtOptions_Radians_StepSize.KeyDown += formSpriteEditor_2017.instance.txt_KeyDown_NumericOnly;
            txtOptions_Radians_StepSize.TextChanged += TxtOptions_Radians_StepSize_TextChanged;
            txtOptions_Radians_StepSize.MouseWheel += formSpriteEditor_2017.instance.Txt_Radians_MouseWheel;

            pnlContainer.Controls.Add(lblOptions_DrawAngle);
            lblOptions_DrawAngle.Name = "lblOptions_DrawAngle";
            lblOptions_DrawAngle.Text = "Draw Angle";

            pnlContainer.Controls.Add(txtOptions_DrawAngle);
            txtOptions_DrawAngle.Name = "txtOptions_DrawAngle";
            
            txtOptions_DrawAngle.KeyDown += formSpriteEditor_2017.instance.txt_KeyDown_NumericOnly;
            txtOptions_DrawAngle.TextChanged += TxtOptions_DrawAngle_TextChanged;
            txtOptions_DrawAngle.MouseWheel += formSpriteEditor_2017.instance.Txt_Radians_MouseWheel;

            pnlContainer.Controls.Add(lblTimerDelay);
            lblTimerDelay.Name = "lblTimerDelay";
            lblTimerDelay.Text = "Timer Delay";

            pnlContainer.Controls.Add(txtTimerDelay);
            txtTimerDelay.Name = "txtTimerDelay";
            txtTimerDelay.Text = formSpriteEditor_2017.instance.tmrAnimation.Interval.ToString();
            txtTimerDelay.KeyDown += formSpriteEditor_2017.instance.txt_KeyDown_NumericOnly;
            txtTimerDelay.TextChanged += TxtTimerDelay_TextChanged;

            pnlContainer.Controls.Add(chkShow_LimbCenters);
            chkShow_LimbCenters.Name = "chkShow_LimbCenters";
            chkShow_LimbCenters.Text = "Show Limb &Centers";
            chkShow_LimbCenters.CheckedChanged += chk_Draw_Sprite_onCheckedChanged;
            pnlContainer.Controls.Add(chkShow_LimbNames);
            chkShow_LimbNames.Name = "chkShow_LimbNames";
            chkShow_LimbNames.Text = "Show Limb &Names";
            chkShow_LimbNames.CheckedChanged += chk_Draw_Sprite_onCheckedChanged;
            pnlContainer.Controls.Add(chkShow_LimbPositions);
            chkShow_LimbPositions.Name = "chkShow_LimbPositions";
            chkShow_LimbPositions.Text = "Show Limb &Positions";
            chkShow_LimbPositions.CheckedChanged += chk_Draw_Sprite_onCheckedChanged;
            chkShow_LimbPositions.MouseEnter += ChkShow_LimbPositions_MouseEnter;
            chkShow_LimbPositions.MouseLeave += ChkShow_LimbPositions_MouseLeave;

            pnlContainer.Controls.Add(clbShow_LimbPositions);
            clbShow_LimbPositions.Name = "clbShow_LimbPositions";
            clbShow_LimbPositions.MouseEnter += ClbShow_LimbPositions_MouseEnter;
            clbShow_LimbPositions.MouseLeave += ClbShow_LimbPositions_MouseLeave;
            clbShow_LimbPositions.CheckOnClick = true;
            clbShow_LimbPositions.Click += ClbShow_LimbPositions_Click;

            pnlContainer.Controls.Add(chkShow_FocusController);
            chkShow_FocusController.Name = "chkShow_FocusController";
            chkShow_FocusController.Text = "Show Focus ";
            chkShow_FocusController.CheckedChanged += chk_Draw_Sprite_onCheckedChanged;
            pnlContainer.Controls.Add(chkShow_ToolTips);
            chkShow_ToolTips.Checked = true;
            chkShow_ToolTips.Name = "chkShow_ToolTips";
            chkShow_ToolTips.Text = "Show Tool Tips";
            chkShow_ToolTips.CheckedChanged += ChkShow_ToolTips_CheckedChanged;

            pnlContainer.Controls.Add(chkUseRAMCache);
            chkUseRAMCache.Name = "chkUseRAMCache";
            chkUseRAMCache.Text = "Use RAM Cache";
            chkUseRAMCache.CheckedChanged += chkUseRAMCache_CheckedChanged;

            int intMinWidth = 0;
            int intMinHeight = 0;
            int intLeft = 5;
            pnlContainer.Controls.Add(grbRotatedLimbImage);
            grbRotatedLimbImage.Text = "Limb Rotation Source";
            for (int intRotatedLimbImage = 0; intRotatedLimbImage < (int)classSprite.enuRotatedLimbImage._numRotatedLimbImage; intRotatedLimbImage++)
            {
                classSprite.enuRotatedLimbImage eRotatedLimbImage = (classSprite.enuRotatedLimbImage)intRotatedLimbImage;
                RadioButton rdb = new RadioButton();
                lstLimbImageRotationSelection.Add(rdb);

                rdb.Text = eRotatedLimbImage.ToString();
                rdb.AutoSize = true;
                grbRotatedLimbImage.Controls.Add(rdb);

                rdb.Left = intLeft;
                rdb.Top = 15 + rdb.Height * intRotatedLimbImage;
                rdb.CheckedChanged += rdbRotatedLimbImage_CheckChanged;

                if (intMinWidth < rdb.Width)
                    intMinWidth = rdb.Width;
                intMinHeight = rdb.Bottom + 5;
            }
            grbRotatedLimbImage.Width = intMinWidth + 10;
            grbRotatedLimbImage.Height = intMinHeight;

            pnlContainer.Controls.Add(chkShow_Frame);
            chkShow_Frame.Name = "chkShow_Frame";
            chkShow_Frame.Text = "Show Frame";

            lblFocusController_StepSize.ForeColor
                = lblOptions_DrawAngle.ForeColor
                = lblOptions_Magnitude_StepSize.ForeColor
                = lblOptions_Radians_StepSize.ForeColor
                = lblTimerDelay.ForeColor
                = pnlContainer.ForeColor;

            lblFocusController_StepSize.BackColor
                = lblOptions_DrawAngle.BackColor
                = lblOptions_Magnitude_StepSize.BackColor
                = lblOptions_Radians_StepSize.BackColor
                = lblTimerDelay.BackColor
                = pnlContainer.BackColor;

            txtFocusController_StepSize.ForeColor
                = txtOptions_DrawAngle.ForeColor
                = txtOptions_Magnitude_StepSize.ForeColor
                = txtOptions_Radians_StepSize.ForeColor
                = txtTimerDelay.ForeColor
                = pnlContainer.ForeColor;

            txtFocusController_StepSize.BackColor
                = txtOptions_DrawAngle.BackColor
                = txtOptions_Magnitude_StepSize.BackColor
                = txtOptions_Radians_StepSize.BackColor
                = txtTimerDelay.BackColor
                = pnlContainer.BackColor;

            chkShow_FocusController.ForeColor
                = chkShow_Frame.ForeColor
                = chkShow_LimbCenters.ForeColor
                = chkShow_LimbNames.ForeColor
                = chkShow_ToolTips .ForeColor 
                = chkUseRAMCache.ForeColor
                = pnlContainer.ForeColor;

            chkShow_FocusController.BackColor
                = chkShow_Frame.BackColor
                = chkShow_LimbCenters.BackColor
                = chkShow_LimbNames.BackColor
                = chkShow_ToolTips.BackColor 
                = chkUseRAMCache.BackColor
                = pnlContainer.BackColor;

            grbRotatedLimbImage.ForeColor = pnlContainer.ForeColor;
            grbRotatedLimbImage.BackColor = pnlContainer.BackColor;

            setToolTip();


            init_Format();

            ContextMenu = formSpriteEditor_2017.instance.cMnuPic;

            LocationChanged += PanelOptions_LocationChanged;
            SizeChanged += PanelOptions_SizeChanged;
            Disposed += PanelOptions_Disposed;
        }


        public void init_Format()
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolIgnoreChanges = true;
            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options] != null)
            {
                Size = new Size(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].size_Width,
                                 formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].size_Height);
            }
            else
                Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options] != null)
                ExpansionDirection = formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].ExpansionDirection;
            else
                ExpansionDirection = enuExpansionDirection.Down;

            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options] != null)
            {
                if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].Collapsed)
                    Collapse();
                else
                    Expand();
            }
            else
                Expand();

            if (formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options] != null)
            {
                Location = new Point(formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].location_X,
                                   formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].location_Y);
            }
            else
            {
                Location = new Point(0, 0);
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolIgnoreChanges = false;


            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_MagnitudeStepSize] != null)
                txtOptions_Magnitude_StepSize.Text = ((double)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_MagnitudeStepSize]).ToString(formSpriteEditor_2017.strMagnitudeFormat);
            else
                txtOptions_Magnitude_StepSize.Text = "10";

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_RadiansStepSize] != null)
                txtOptions_Radians_StepSize.Text = ((double)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_RadiansStepSize]).ToString(formSpriteEditor_2017.strRadiansFormat);
            else
                txtOptions_Radians_StepSize.Text = "0.1";

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_DrawAngle] != null)
                txtOptions_DrawAngle.Text = ((double)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_DrawAngle]).ToString(formSpriteEditor_2017.strRadiansFormat);
            else
                txtOptions_DrawAngle.Text = ".1";

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

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

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

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Show_FocusController_checked] != null)
                chkShow_FocusController.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Show_FocusController_checked]);
            else
                chkShow_FocusController.Checked = true;

            if (formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Show_ToolTips_checked] != null)
                chkShow_ToolTips.Checked = ((bool)formSpriteEditor_2017.instance.objOptions[(int)formSpriteEditor_2017.enuOptions.Options_Show_ToolTips_checked]);
            else
                chkShow_ToolTips.Checked = true;

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

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

            placeObjects();
        }

        /// <summary>
        /// toggles use of tooltips according to user's selection
        /// </summary>
        private void ChkShow_ToolTips_CheckedChanged(object sender, EventArgs e)
        {
            formSpriteEditor_2017.instance.ToolTips_Enabled = chkShow_ToolTips.Checked;
        }

        /// <summary>
        /// binds panel's controls to the formSpriteEditor_2017 tooltip
        /// </summary>
        void setToolTip()
        {
            ToolTip tt = formSpriteEditor_2017.instance.toolTip;
            // pnlOptions
            tt.SetToolTip(lblOptions_Magnitude_StepSize, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtOptions_Magnitude_StepSize, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblOptions_Radians_StepSize, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtOptions_Radians_StepSize, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblOptions_DrawAngle, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtOptions_DrawAngle, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblFocusController_StepSize, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtFocusController_StepSize, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(lblTimerDelay, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(txtTimerDelay, formSpriteEditor_2017.conDefaultToolTip);

            tt.SetToolTip(chkShow_LimbNames, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkShow_LimbPositions, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(clbShow_LimbPositions, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkShow_LimbCenters, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkShow_FocusController, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkShow_Frame, formSpriteEditor_2017.conDefaultToolTip);
            tt.SetToolTip(chkUseRAMCache, formSpriteEditor_2017.conDefaultToolTip);



        }

        /// <summary>
        /// sets the boolean value of the limb selected in the checkedlistbox Show_LimbPositions after the user checked that UI
        /// </summary>
        private void ClbShow_LimbPositions_Click(object sender, EventArgs e)
        {
            string strSelectedLimb = clbShow_LimbPositions.Items[clbShow_LimbPositions.SelectedIndex].ToString();
            classSprite_Limb cLimbSelected = (classSprite_Limb)cSprite.cCostumeInfo_Default.cBT_Limbs.Search(strSelectedLimb);
            if (cLimbSelected != null)
                cLimbSelected.DisplayPosition = !clbShow_LimbPositions.GetItemChecked(clbShow_LimbPositions.SelectedIndex);
        }

        public classSprite cSprite;
        /// <summary>
        /// sets the checkedListBox ShowLimbPositions to the sprite's limbs current states
        /// </summary>
        public void clbShowLimbPositions_Set()
        {
            cSprite = formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite;
            clbShow_LimbPositions.Items.Clear();
            List<string> lstNames = new List<string>();
            for (int intLimbCounter = 0; intLimbCounter < cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
            {
                classSprite_Limb cLimb = cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter];
                lstNames.Add(cLimb.Name);
            }

            IEnumerable<string> query = lstNames.OrderBy(num => num, new classSpriteMaker.Compare_Alphabetical());
            lstNames = query.ToList<string>();

            for (int intLimbCounter = 0; intLimbCounter < cSprite.cCostumeInfo_Default.lstLimbs.Count; intLimbCounter++)
            {
                clbShow_LimbPositions.Items.Add(lstNames[intLimbCounter]);
                classSprite_Limb cLimb = cSprite.cCostumeInfo_Default.lstLimbs[intLimbCounter];
                clbShow_LimbPositions.SetItemChecked(intLimbCounter, cLimb.DisplayPosition);
            }
        }

        /// <summary>
        /// facilitates mouseLeave/Enter transitions between ShowLimbPositions checkBox and CheckedListBox 
        /// </summary>
        private void TmrShowLimbPositions_Hide_Tick(object sender, EventArgs e)
        {
            tmrShowLimbPositions_Hide.Enabled = false;
            clbShow_LimbPositions.Hide();
        }

        /// <summary>
        /// sets timer to hide checkedListBox Show_LimbPositions 
        /// </summary>
        private void ClbShow_LimbPositions_MouseLeave(object sender, EventArgs e)
        {
            tmrShowLimbPositions_Hide.Enabled = true;
        }

        /// <summary>
        /// disables timer set to hide the checkedListBox Show_LimbPositions
        /// </summary>
        private void ClbShow_LimbPositions_MouseEnter(object sender, EventArgs e)
        {
            tmrShowLimbPositions_Hide.Enabled = false;
            clbShow_LimbPositions.Visible = true;
        }

        /// <summary>
        /// sets timer to hide checkedListBox Show_LimbPositions 
        /// </summary>
        private void ChkShow_LimbPositions_MouseLeave(object sender, EventArgs e)
        {
            tmrShowLimbPositions_Hide.Enabled = true;
        }

        /// <summary>
        /// disables timer set to hide the checkedListBox Show_LimbPositions
        /// </summary>
        private void ChkShow_LimbPositions_MouseEnter(object sender, EventArgs e)
        {
            tmrShowLimbPositions_Hide.Enabled = false;
            clbShow_LimbPositions.Visible = chkShow_LimbPositions.Checked;
        }

        /// <summary>
        /// sets the sprite's MasterLimb's draw angle to the value the user set in the Options_DrawAngle textbox
        /// </summary>
        private void TxtOptions_DrawAngle_TextChanged(object sender, EventArgs e)
        {
            double dbl_Radians_StepSize = formSpriteEditor_2017.txtBox_ReadValue(txtOptions_DrawAngle.Text);
            if (formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite != null)
            {
                formSpriteEditor_2017.instance.cSpriteData.cAnimationData.dblDrawAngle = dbl_Radians_StepSize;
                formSpriteEditor_2017.instance.Draw_Sprite();
            }
        }

        void rdbRotatedLimbImage_CheckChanged(object sender, EventArgs e)
        {
            for (int intRdbCounter = 0; intRdbCounter < lstLimbImageRotationSelection.Count; intRdbCounter++)
            {
                RadioButton rdb = lstLimbImageRotationSelection[intRdbCounter];
                if (rdb.Checked)
                {
                    cSprite.eRotatedLimbImage = (classSprite.enuRotatedLimbImage)intRdbCounter;
                    return;
                }
            }
        }


        /// <summary>
        /// sets the sprite's UseRAMCache value to that set by the user with the checkbox UseRAMCache
        /// </summary>
        private void chkUseRAMCache_CheckedChanged(object sender, EventArgs e)
        {
            if (formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite != null)
            {
                formSpriteEditor_2017.instance.cSpriteData.cAnimationData.cSprite.UseRamCache = chkUseRAMCache.Checked;
                chkUseRAMCache.BackColor = (chkUseRAMCache.Checked ? Color.Yellow : pnlContainer.BackColor);
                
            }
        }

        /// <summary>
        /// called generically by various checkedboxes to reflect the change in the user's option choices 
        /// </summary>
        private void chk_Draw_Sprite_onCheckedChanged(object sender, EventArgs e)
        {
            formSpriteEditor_2017.instance.Draw_Sprite();
        }

        /// <summary>
        /// sets the timer tmrAnimation's delay
        /// </summary>
        private void TxtTimerDelay_TextChanged(object sender, EventArgs e)
        {
            int intTimerDelay = (int)formSpriteEditor_2017.txtBox_ReadValue(txtTimerDelay.Text);
            if (intTimerDelay > 0)
            {
                formSpriteEditor_2017.instance.tmrAnimation.Interval = intTimerDelay;
            }
            else
                txtTimerDelay.Text = "500";
        }

        /// <summary>
        /// sets the value by which all textboxes reflecting radian variables are changed using the MouseWheel
        /// </summary>
        private void TxtOptions_Radians_StepSize_TextChanged(object sender, EventArgs e)
        {
            double dbl_Radians_StepSize = formSpriteEditor_2017.txtBox_ReadValue(txtOptions_Radians_StepSize.Text);
            formSpriteEditor_2017.dbl_Radians_StepSize = dbl_Radians_StepSize;
        }

        /// <summary>
        /// sets the value by which all textboxes reflecting magnitude variables are changed using the MouseWheel
        /// </summary>
        private void TxtOptions_Magnitude_StepSize_TextChanged(object sender, EventArgs e)
        {
            double dbl_Magnitude_StepSize = formSpriteEditor_2017.txtBox_ReadValue(txtOptions_Magnitude_StepSize.Text);
            formSpriteEditor_2017.dbl_Magnitude_StepSize = dbl_Magnitude_StepSize;
        }

        /// <summary>
        /// changes the value by which the FocusControl move functions move the sprite on the screen
        /// </summary>
        private void TxtFocusController_StepSize_TextChanged(object sender, EventArgs e)
        {
            double dblFocusController_StepSize = formSpriteEditor_2017.txtBox_ReadValue(txtFocusController_StepSize.Text);
            formSpriteEditor_2017.intFocusController_StepSize = (int)dblFocusController_StepSize;
        }

        /// <summary>
        /// records panel's Collapsed/ExpansionDirection states for formatting purposes
        /// </summary>
        private void PanelOptions_Disposed(object sender, EventArgs e)
        {
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].Collapsed = Collapsed;
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].ExpansionDirection = ExpansionDirection;
        }

        /// <summary>
        /// records the panel's location after a location change for formatting purposes
        /// </summary>
        private void PanelOptions_LocationChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolIgnoreChanges)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].location_X = Location.X;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].location_Y = Location.Y;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolInit = true;
            }
        }

        /// <summary>
        /// records the panel size after a size change for formatting purposes
        /// </summary>
        private void PanelOptions_SizeChanged(object sender, EventArgs e)
        {
            if (!formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolIgnoreChanges
                && !Collapsed)
            {
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].bolInit = true;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].size_Width = Size.Width;
                formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].size_Height = Size.Height;
            }
            formSpriteEditor_2017.cPanelSizeLocations[(int)formSpriteEditor_2017.enuPanels.Options].Collapsed = Collapsed;

            placeObjects();
        }

        /// <summary>
        /// places controls on the panel after a size change
        /// </summary>
        public void placeObjects()
        {
            List<Label> lstLabels = new List<Label>();
            lstLabels.Add(lblOptions_Radians_StepSize);
            lstLabels.Add(lblOptions_Magnitude_StepSize);
            lstLabels.Add(lblFocusController_StepSize);
            lstLabels.Add(lblTimerDelay);
            lstLabels.Add(lblOptions_DrawAngle);

            List<TextBox> lstTextBoxes = new List<TextBox>();
            lstTextBoxes.Add(txtOptions_Radians_StepSize);
            lstTextBoxes.Add(txtOptions_Magnitude_StepSize);
            lstTextBoxes.Add(txtFocusController_StepSize);
            lstTextBoxes.Add(txtTimerDelay);
            lstTextBoxes.Add(txtOptions_DrawAngle);

            txtFocusController_StepSize.Text = formSpriteEditor_2017.intFocusController_StepSize.ToString();
            txtOptions_Magnitude_StepSize.Text = formSpriteEditor_2017.dbl_Magnitude_StepSize.ToString(formSpriteEditor_2017.strMagnitudeFormat);
            txtOptions_Radians_StepSize.Text = formSpriteEditor_2017.dbl_Radians_StepSize.ToString(formSpriteEditor_2017.strRadiansFormat);
            txtTimerDelay.Text = formSpriteEditor_2017.instance.tmrAnimation.Interval.ToString();

            int intLeftText = 0;
            for (int intLabelCounter = 0; intLabelCounter < lstLabels.Count; intLabelCounter++)
            {
                if (lstLabels[intLabelCounter].Right > intLeftText)
                    intLeftText = lstLabels[intLabelCounter].Right;
                lstLabels[intLabelCounter].Left = 0;
                if (intLabelCounter > 0)
                {
                    lstLabels[intLabelCounter].Top
                    = lstLabels[intLabelCounter - 1].Bottom;
                }
            }

            for (int intTextBoxCounter = 0; intTextBoxCounter < lstTextBoxes.Count; intTextBoxCounter++)
            {
                lstTextBoxes[intTextBoxCounter].Left = 0;

                lstTextBoxes[intTextBoxCounter].Top = lstLabels[intTextBoxCounter].Top;
                lstTextBoxes[intTextBoxCounter].Left = intLeftText;
                lstTextBoxes[intTextBoxCounter].Width = pnlContainer.Width - lstTextBoxes[intTextBoxCounter].Left - 1;
            }

            txtOptions_Radians_StepSize.Left
                = txtOptions_Magnitude_StepSize.Left
                = txtFocusController_StepSize.Left
                = intLeftText;


            grbRotatedLimbImage.Top = Height - grbRotatedLimbImage.Height - 5; ;
            grbRotatedLimbImage.Left = 4;

            List<CheckBox> lstCheckBoxes = new List<CheckBox>();
            lstCheckBoxes.Add(chkShow_LimbPositions);
            lstCheckBoxes.Add(chkShow_LimbCenters);
            lstCheckBoxes.Add(chkShow_LimbNames);
            lstCheckBoxes.Add(chkShow_Frame);
            lstCheckBoxes.Add(chkShow_ToolTips);
            //lstCheckBoxes.Add(null);
            lstCheckBoxes.Add(chkShow_FocusController);
            //lstCheckBoxes.Add(null);
            lstCheckBoxes.Add(chkUseRAMCache);

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


            clbShow_LimbPositions.Height = chkShow_LimbPositions.Top;
            clbShow_LimbPositions.Top = chkShow_LimbPositions.Top - clbShow_LimbPositions.Height ;
            clbShow_LimbPositions.Left = chkShow_LimbPositions.Left;
            clbShow_LimbPositions.Width = pnlContainer.Width - clbShow_LimbPositions.Left - 2;
            clbShow_LimbPositions.Visible = false;
            clbShow_LimbPositions.BringToFront();
        }

    }

    /// <summary>
    /// class used to record formatting data that is saved at application's disposal and loaded at application's launch to initialize panels and options 
    /// to the same values they were when the user last quit the application
    /// </summary>
    public class classPanelSizeLocation
    {
        Size _size = new Size(300, 300);
        public int size_Height
        {
            get { return _size.Height; }
            set
            {
                if (bolIgnoreChanges) return;
                if (value > 25)
                    _size.Height = value;
            }
        }
        public int size_Width
        {
            get { return _size.Width; }
            set
            {
                if (bolIgnoreChanges) return;
                if (value > 25)
                    _size.Width = value;
            }
        }

        Point _location = new Point(300, 300);
        public int location_X
        {
            get { return _location.X; }
            set
            {
                if (bolIgnoreChanges) return;
                if (value > 0 && value < Screen.PrimaryScreen.WorkingArea.Width)
                    _location.X = value;
            }
        }

        public int location_Y
        {
            get { return _location.Y; }
            set
            {
                if (bolIgnoreChanges) return;
                if (value > 0 && value < Screen.PrimaryScreen.WorkingArea.Width)
                    _location.Y = value;
            }
        }

        bool _collapsed;
        public bool Collapsed
        {
            get { return _collapsed; }
            set { _collapsed = value; }
        }

        public bool bolInit = false;

        public bool bolIgnoreChanges = false;

        panelMoveable.enuExpansionDirection eExpansionDirection = panelMoveable.enuExpansionDirection.Up;
        public panelMoveable.enuExpansionDirection ExpansionDirection
        {
            get { return eExpansionDirection; }
            set { eExpansionDirection = value; }
        }

    }

   

}
