Created dedicated drop-down UI control, integrated it and fixed some bugs.
[VesselSimulator.git] / KerbalEngineer / Flight / Sections / SectionEditor.cs
blob:a/KerbalEngineer/Flight/Sections/SectionEditor.cs -> blob:b/KerbalEngineer/Flight/Sections/SectionEditor.cs
--- a/KerbalEngineer/Flight/Sections/SectionEditor.cs
+++ b/KerbalEngineer/Flight/Sections/SectionEditor.cs
@@ -22,6 +22,7 @@
 using System;
 
 using KerbalEngineer.Extensions;
+using KerbalEngineer.Flight.Presets;
 using KerbalEngineer.Flight.Readouts;
 using KerbalEngineer.UIControls;
 
@@ -35,78 +36,325 @@
     {
         #region Constants
 
+        public const float Height = 500.0f;
         public const float Width = 500.0f;
-        public const float Height = 500.0f;
 
         #endregion
 
         #region Fields
 
-        private Vector2 scrollPositionAvailable;
-        private Vector2 scrollPositionInstalled;
-        private Rect position;
+        private GUIStyle categoryButtonActiveStyle;
+        private GUIStyle categoryButtonStyle;
         private DropDown categoryList;
-
-        #endregion
-
-        #region Constructors
-
-        private void Awake()
-        {
-            try
-            {
-                this.categoryList = this.gameObject.AddComponent<DropDown>();
-                this.categoryList.DrawCallback = this.DrawCategories;
-            }
-            catch (Exception ex)
-            {
-                Logger.Exception(ex);
-            }
-        }
-
-        /// <summary>
-        ///     Initialises the object's state on creation.
-        /// </summary>
-        private void Start()
-        {
-            this.InitialiseStyles();
-            ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
-            RenderingManager.AddToPostDrawQueue(0, this.Draw);
-        }
-
-        #endregion
-
-        #region Properties
-
-        /// <summary>
-        ///     Gets and sets the parent section for the section editor.
-        /// </summary>
-        public SectionModule ParentSection { get; set; }
-
-        /// <summary>
-        ///     Gets and sets the window position.
-        /// </summary>
-        public Rect Position
-        {
-            get { return this.position; }
-            set { this.position = value; }
-        }
-
-        #endregion
-
-        #region GUIStyles
-
         private GUIStyle categoryTitleButtonStyle;
-        private GUIStyle categoryButtonStyle;
-        private GUIStyle categoryButtonActiveStyle;
         private GUIStyle helpBoxStyle;
         private GUIStyle helpTextStyle;
         private GUIStyle panelTitleStyle;
+        private Rect position;
+        private DropDown presetList;
         private GUIStyle readoutButtonStyle;
         private GUIStyle readoutNameStyle;
+        private Vector2 scrollPositionAvailable;
+        private Vector2 scrollPositionInstalled;
         private GUIStyle textStyle;
         private GUIStyle windowStyle;
 
+        #endregion
+
+        #region Properties
+
+        /// <summary>
+        ///     Gets and sets the parent section for the section editor.
+        /// </summary>
+        public SectionModule ParentSection { get; set; }
+
+        /// <summary>
+        ///     Gets and sets the window position.
+        /// </summary>
+        public Rect Position
+        {
+            get { return this.position; }
+            set { this.position = value; }
+        }
+
+        #endregion
+
+        #region Methods: protected
+
+        protected void Awake()
+        {
+            try
+            {
+                this.categoryList = this.gameObject.AddComponent<DropDown>();
+                this.categoryList.DrawCallback = this.DrawCategories;
+                this.presetList = this.gameObject.AddComponent<DropDown>();
+                this.presetList.DrawCallback = this.DrawPresets;
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        /// <summary>
+        ///     Runs when the object is destroyed.
+        /// </summary>
+        protected void OnDestroy()
+        {
+            try
+            {
+                RenderingManager.RemoveFromPostDrawQueue(0, this.Draw);
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        /// <summary>
+        ///     Initialises the object's state on creation.
+        /// </summary>
+        protected void Start()
+        {
+            try
+            {
+                this.InitialiseStyles();
+                //ReadoutCategory.Selected = ReadoutCategory.GetCategory("Orbital");
+                RenderingManager.AddToPostDrawQueue(0, this.Draw);
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
+        }
+
+        #endregion
+
+        #region Methods: private
+
+        /// <summary>
+        ///     Called to draw the editor when the UI is enabled.
+        /// </summary>
+        private void Draw()
+        {
+            this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, "EDIT SECTION - " + this.ParentSection.Name.ToUpper(), this.windowStyle).ClampToScreen();
+            this.ParentSection.EditorPositionX = this.position.x;
+            this.ParentSection.EditorPositionY = this.position.y;
+        }
+
+        /// <summary>
+        ///     Draws the available readouts panel.
+        /// </summary>
+        private void DrawAvailableReadouts()
+        {
+            GUI.skin = HighLogic.Skin;
+            this.scrollPositionAvailable = GUILayout.BeginScrollView(this.scrollPositionAvailable, false, true, GUILayout.Height(200.0f));
+            GUI.skin = null;
+
+            GUILayout.Label("AVAILABLE", this.panelTitleStyle);
+
+            foreach (var readout in ReadoutLibrary.GetCategory(ReadoutCategory.Selected))
+            {
+                if (!this.ParentSection.ReadoutModules.Contains(readout) || readout.Cloneable)
+                {
+                    GUILayout.BeginHorizontal(GUILayout.Height(30.0f));
+                    GUILayout.Label(readout.Name, this.readoutNameStyle);
+                    readout.ShowHelp = GUILayout.Toggle(readout.ShowHelp, "?", this.readoutButtonStyle, GUILayout.Width(30.0f));
+                    if (GUILayout.Button("INSTALL", this.readoutButtonStyle, GUILayout.Width(125.0f)))
+                    {
+                        this.ParentSection.ReadoutModules.Add(readout);
+                    }
+                    GUILayout.EndHorizontal();
+
+                    this.ShowHelpMessage(readout);
+                }
+            }
+
+            GUILayout.EndScrollView();
+        }
+
+        /// <summary>
+        ///     Draws the categories list drop down UI.
+        /// </summary>
+        private void DrawCategories()
+        {
+            foreach (var category in ReadoutCategory.Categories)
+            {
+                var description = category.Description;
+                if (description.Length > 50)
+                {
+                    description = description.Substring(0, 50 - 1) + "...";
+                }
+
+                if (GUILayout.Button("<b>" + category.Name.ToUpper() + "</b>" + (string.IsNullOrEmpty(category.Description) ? string.Empty : "\n<i>" + description + "</i>"), category == ReadoutCategory.Selected ? this.categoryButtonActiveStyle : this.categoryButtonStyle))
+                {
+                    ReadoutCategory.Selected = category;
+                    this.categoryList.enabled = false;
+                }
+            }
+        }
+
+        /// <summary>
+        ///     Draws the readoutCategories selection list.
+        /// </summary>
+        private void DrawCategorySelector()
+        {
+            this.categoryList.enabled = GUILayout.Toggle(this.categoryList.enabled, "▼ SELECTED CATEGORY: " + ReadoutCategory.Selected.ToString().ToUpper() + " ▼", this.categoryTitleButtonStyle);
+            if (Event.current.type == EventType.repaint)
+            {
+                this.categoryList.SetPosition(GUILayoutUtility.GetLastRect().Translate(this.position));
+            }
+        }
+
+        /// <summary>
+        ///     Draws the options for editing custom sections.
+        /// </summary>
+        private void DrawCustomOptions()
+        {
+            GUILayout.BeginHorizontal(GUILayout.Height(25.0f));
+            this.ParentSection.Name = GUILayout.TextField(this.ParentSection.Name, this.textStyle);
+            var isShowingInControlBar = !string.IsNullOrEmpty(this.ParentSection.Abbreviation);
+            this.ParentSection.Abbreviation = GUILayout.TextField(this.ParentSection.Abbreviation, this.textStyle, GUILayout.Width(75.0f));
+
+            ParentSection.IsHud = GUILayout.Toggle(this.ParentSection.IsHud, "HUD", this.readoutButtonStyle, GUILayout.Width(50.0f));
+            if (ParentSection.IsHud)
+            {
+                this.ParentSection.IsHudBackground = GUILayout.Toggle(this.ParentSection.IsHudBackground, "BG", this.readoutButtonStyle, GUILayout.Width(50.0f));
+            }
+
+            if (this.ParentSection.IsCustom)
+            {
+                if (isShowingInControlBar && string.IsNullOrEmpty(this.ParentSection.Abbreviation))
+                {
+                    DisplayStack.Instance.RequestResize();
+                }
+
+                if (GUILayout.Button("DELETE SECTION", this.readoutButtonStyle, GUILayout.Width(150.0f)))
+                {
+                    this.ParentSection.IsFloating = false;
+                    this.ParentSection.IsEditorVisible = false;
+                    SectionLibrary.CustomSections.Remove(this.ParentSection);
+                    DisplayStack.Instance.RequestResize();
+                }
+            }
+            GUILayout.EndHorizontal();
+        }
+
+        /// <summary>
+        ///     Draws the installed readouts panel.
+        /// </summary>
+        private void DrawInstalledReadouts()
+        {
+            GUI.skin = HighLogic.Skin;
+            this.scrollPositionInstalled = GUILayout.BeginScrollView(this.scrollPositionInstalled, false, true);
+            GUI.skin = null;
+
+            GUILayout.Label("INSTALLED", this.panelTitleStyle);
+            var removeReadout = false;
+            var removeReadoutIndex = 0;
+
+            for (var i = 0; i < this.ParentSection.ReadoutModules.Count; i++)
+            {
+                var readout = this.ParentSection.ReadoutModules[i];
+
+                GUILayout.BeginHorizontal(GUILayout.Height(30.0f));
+                GUILayout.Label(readout.Name, this.readoutNameStyle);
+                if (GUILayout.Button("▲", this.readoutButtonStyle, GUILayout.Width(30.0f)))
+                {
+                    if (i > 0)
+                    {
+                        this.ParentSection.ReadoutModules[i] = this.ParentSection.ReadoutModules[i - 1];
+                        this.ParentSection.ReadoutModules[i - 1] = readout;
+                    }
+                }
+                if (GUILayout.Button("▼", this.readoutButtonStyle, GUILayout.Width(30.0f)))
+                {
+                    if (i < this.ParentSection.ReadoutModules.Count - 1)
+                    {
+                        this.ParentSection.ReadoutModules[i] = this.ParentSection.ReadoutModules[i + 1];
+                        this.ParentSection.ReadoutModules[i + 1] = readout;
+                    }
+                }
+                readout.ShowHelp = GUILayout.Toggle(readout.ShowHelp, "?", this.readoutButtonStyle, GUILayout.Width(30.0f));
+                if (GUILayout.Button("REMOVE", this.readoutButtonStyle, GUILayout.Width(125.0f)))
+                {
+                    removeReadout = true;
+                    removeReadoutIndex = i;
+                }
+                GUILayout.EndHorizontal();
+
+                this.ShowHelpMessage(readout);
+            }
+
+            GUILayout.EndScrollView();
+
+            if (removeReadout)
+            {
+                this.ParentSection.ReadoutModules.RemoveAt(removeReadoutIndex);
+            }
+        }
+
+        private void DrawPresetButton(Preset preset)
+        {
+            if (!GUILayout.Button("<b>" + preset.Name.ToUpper() + "</b>", this.categoryButtonStyle))
+            {
+                return;
+            }
+
+            this.ParentSection.Name = preset.Name;
+            this.ParentSection.Abbreviation = preset.Abbreviation;
+            this.ParentSection.ReadoutModuleNames = preset.ReadoutNames;
+            this.ParentSection.IsHud = preset.IsHud;
+            this.ParentSection.IsHudBackground = preset.IsHudBackground;
+            this.presetList.enabled = false;
+        }
+
+        private void DrawPresetSaveButton()
+        {
+            if (!GUILayout.Button("<b>SAVE PRESET</b>", this.categoryButtonStyle))
+            {
+                return;
+            }
+
+            this.SavePreset(PresetLibrary.Presets.Find(p => String.Equals(p.Name, this.ParentSection.Name, StringComparison.CurrentCultureIgnoreCase)));
+        }
+
+        /// <summary>
+        ///     Draws the presetsList selection list.
+        /// </summary>
+        private void DrawPresetSelector()
+        {
+            this.presetList.enabled = GUILayout.Toggle(this.presetList.enabled, "▼ PRESETS ▼", this.categoryTitleButtonStyle, GUILayout.Width(150.0f));
+            if (Event.current.type == EventType.repaint)
+            {
+                this.presetList.SetPosition(GUILayoutUtility.GetLastRect().Translate(this.position));
+            }
+        }
+
+        /// <summary>
+        ///     Draws the preset list drop down UI.
+        /// </summary>
+        private void DrawPresets()
+        {
+            Preset removePreset = null;
+            foreach (var preset in PresetLibrary.Presets)
+            {
+                GUILayout.BeginHorizontal();
+                this.DrawPresetButton(preset);
+                if (GUILayout.Button("<b>X</b>", this.categoryButtonStyle, GUILayout.Width(30.0f)))
+                {
+                    removePreset = preset;
+                }
+                GUILayout.EndHorizontal();
+            }
+            if (removePreset != null && PresetLibrary.Remove(removePreset))
+            {
+                this.presetList.Resize = true;
+            }
+
+            this.DrawPresetSaveButton();
+        }
+
         /// <summary>
         ///     Initialises all the styles required for this object.
         /// </summary>
@@ -120,8 +368,8 @@
                 {
                     textColor = Color.white
                 },
-                margin = new RectOffset(0,0,2,0),
-                padding = new RectOffset(5,5,5,5),
+                margin = new RectOffset(0, 0, 2, 0),
+                padding = new RectOffset(5, 5, 5, 5),
                 alignment = TextAnchor.MiddleCenter,
                 fontSize = 12,
                 fontStyle = FontStyle.Normal,
@@ -214,18 +462,32 @@
             };
         }
 
-        #endregion
-
-        #region Drawing
-
-        /// <summary>
-        ///     Called to draw the editor when the UI is enabled.
-        /// </summary>
-        private void Draw()
-        {
-            this.position = GUILayout.Window(this.GetInstanceID(), this.position, this.Window, "EDIT SECTION - " + this.ParentSection.Name.ToUpper(), this.windowStyle).ClampToScreen();
-            this.ParentSection.EditorPositionX = this.position.x;
-            this.ParentSection.EditorPositionY = this.position.y;
+        private void SavePreset(Preset preset)
+        {
+            if (preset == null)
+            {
+                preset = new Preset();
+            }
+
+            preset.Name = this.ParentSection.Name;
+            preset.Abbreviation = this.ParentSection.Abbreviation;
+            preset.ReadoutNames = this.ParentSection.ReadoutModuleNames;
+            preset.IsHud = this.ParentSection.IsHud;
+            preset.IsHudBackground = this.ParentSection.IsHudBackground;
+
+            PresetLibrary.Save(preset);
+        }
+
+        private void ShowHelpMessage(ReadoutModule readout)
+        {
+            if (!readout.ShowHelp)
+            {
+                return;
+            }
+
+            GUILayout.BeginVertical(this.helpBoxStyle);
+            GUILayout.Label(!String.IsNullOrEmpty(readout.HelpString) ? readout.HelpString : "Sorry, no help information has been provided for this readout module.", this.helpTextStyle);
+            GUILayout.EndVertical();
         }
 
         /// <summary>
@@ -233,180 +495,28 @@
         /// </summary>
         private void Window(int windowId)
         {
-            this.DrawCustomOptions();
-            this.DrawCategorySelector();
-            this.DrawAvailableReadouts();
-            GUILayout.Space(5.0f);
-            this.DrawInstalledReadouts();
-
-            if (GUILayout.Button("CLOSE EDITOR", this.categoryTitleButtonStyle))
-            {
-                this.ParentSection.IsEditorVisible = false;
-            }
-
-            GUI.DragWindow();
-        }
-
-        /// <summary>
-        ///     Draws the options for editing custom sections.
-        /// </summary>
-        private void DrawCustomOptions()
-        {
-            if (!this.ParentSection.IsCustom)
-            {
-                return;
-            }
-
-            GUILayout.BeginHorizontal(GUILayout.Height(25.0f));
-            this.ParentSection.Name = GUILayout.TextField(this.ParentSection.Name, this.textStyle);
-            this.ParentSection.Abbreviation = GUILayout.TextField(this.ParentSection.Abbreviation, this.textStyle, GUILayout.Width(75.0f));
-            if (GUILayout.Button("DELETE SECTION", this.readoutButtonStyle, GUILayout.Width(125.0f)))
-            {
-                this.ParentSection.IsFloating = false;
-                this.ParentSection.IsEditorVisible = false;
-                SectionLibrary.CustomSections.Remove(this.ParentSection);
-                DisplayStack.Instance.RequestResize();
-            }
-            GUILayout.EndHorizontal();
-        }
-
-        /// <summary>
-        ///     Draws the readoutCategories selection list.
-        /// </summary>
-        private void DrawCategorySelector()
-        {
-            this.categoryList.enabled = GUILayout.Toggle(this.categoryList.enabled, "▼ SELECTED CATEGORY: " + ReadoutCategory.Selected.ToString().ToUpper() + " ▼", this.categoryTitleButtonStyle);
-            if (Event.current.type == EventType.repaint)
-            {
-                this.categoryList.SetPosition(GUILayoutUtility.GetLastRect().Translate(this.position));
-            }
-        }
-
-        private void DrawCategories()
-        {
-            foreach (var category in ReadoutCategory.Categories)
-            {
-                if (GUILayout.Button("<b>" + category.Name.ToUpper() + "</b>" + (string.IsNullOrEmpty(category.Description) ? string.Empty : "\n<i>" + category.Description + "</i>"), category == ReadoutCategory.Selected ? this.categoryButtonActiveStyle : this.categoryButtonStyle))
-                {
-                    ReadoutCategory.Selected = category;
-                    this.categoryList.enabled = false;
-                }
-            }
-        }
-
-        /// <summary>
-        ///     Draws the available readouts panel.
-        /// </summary>
-        private void DrawAvailableReadouts()
-        {
-            GUI.skin = HighLogic.Skin;
-            this.scrollPositionAvailable = GUILayout.BeginScrollView(this.scrollPositionAvailable, false, true, GUILayout.Height(200.0f));
-            GUI.skin = null;
-
-            GUILayout.Label("AVAILABLE", this.panelTitleStyle);
-
-            foreach (var readout in ReadoutLibrary.GetCategory(ReadoutCategory.Selected))
-            {
-                if (!this.ParentSection.ReadoutModules.Contains(readout) || readout.Cloneable)
-                {
-                    GUILayout.BeginHorizontal(GUILayout.Height(30.0f));
-                    GUILayout.Label(readout.Name, this.readoutNameStyle);
-                    readout.ShowHelp = GUILayout.Toggle(readout.ShowHelp, "?", this.readoutButtonStyle, GUILayout.Width(30.0f));
-                    if (GUILayout.Button("INSTALL", this.readoutButtonStyle, GUILayout.Width(125.0f)))
-                    {
-                        this.ParentSection.ReadoutModules.Add(readout);
-                    }
-                    GUILayout.EndHorizontal();
-
-                    this.ShowHelpMessage(readout);
-                }
-            }
-
-            GUILayout.EndScrollView();
-        }
-
-        /// <summary>
-        ///     Draws the installed readouts panel.
-        /// </summary>
-        private void DrawInstalledReadouts()
-        {
-            GUI.skin = HighLogic.Skin;
-            this.scrollPositionInstalled = GUILayout.BeginScrollView(this.scrollPositionInstalled, false, true);
-            GUI.skin = null;
-
-            GUILayout.Label("INSTALLED", this.panelTitleStyle);
-            var removeReadout = false;
-            var removeReadoutIndex = 0;
-
-            for (var i = 0; i < this.ParentSection.ReadoutModules.Count; i++)
-            {
-                var readout = this.ParentSection.ReadoutModules[i];
-
-                GUILayout.BeginHorizontal(GUILayout.Height(30.0f));
-                GUILayout.Label(readout.Name, this.readoutNameStyle);
-                if (GUILayout.Button("▲", this.readoutButtonStyle, GUILayout.Width(30.0f)))
-                {
-                    if (i > 0)
-                    {
-                        this.ParentSection.ReadoutModules[i] = this.ParentSection.ReadoutModules[i - 1];
-                        this.ParentSection.ReadoutModules[i - 1] = readout;
-                    }
-                }
-                if (GUILayout.Button("▼", this.readoutButtonStyle, GUILayout.Width(30.0f)))
-                {
-                    if (i < this.ParentSection.ReadoutModules.Count - 1)
-                    {
-                        this.ParentSection.ReadoutModules[i] = this.ParentSection.ReadoutModules[i + 1];
-                        this.ParentSection.ReadoutModules[i + 1] = readout;
-                    }
-                }
-                readout.ShowHelp = GUILayout.Toggle(readout.ShowHelp, "?", this.readoutButtonStyle, GUILayout.Width(30.0f));
-                if (GUILayout.Button("REMOVE", this.readoutButtonStyle, GUILayout.Width(125.0f)))
-                {
-                    removeReadout = true;
-                    removeReadoutIndex = i;
-                }
+            try
+            {
+                this.DrawCustomOptions();
+                GUILayout.BeginHorizontal();
+                this.DrawCategorySelector();
+                this.DrawPresetSelector();
                 GUILayout.EndHorizontal();
-
-                this.ShowHelpMessage(readout);
-            }
-
-            GUILayout.EndScrollView();
-
-            if (removeReadout)
-            {
-                this.ParentSection.ReadoutModules.RemoveAt(removeReadoutIndex);
-            }
-        }
-
-        private void ShowHelpMessage(ReadoutModule readout)
-        {
-            if (readout.ShowHelp)
-            {
-                GUILayout.BeginVertical(this.helpBoxStyle);
-                if (readout.HelpString != null && readout.HelpString.Length > 0)
-                {
-                    GUILayout.Label(readout.HelpString, this.helpTextStyle);
-                }
-                else
-                {
-                    GUILayout.Label("Sorry, no help information has been provided for this readout module.", this.helpTextStyle);
-                }
-
-                GUILayout.EndVertical();
-            }
-        }
-
-        #endregion
-
-        #region Destruction
-
-        /// <summary>
-        ///     Runs when the object is destroyed.
-        /// </summary>
-        private void OnDestroy()
-        {
-            RenderingManager.RemoveFromPostDrawQueue(0, this.Draw);
+                this.DrawAvailableReadouts();
+                GUILayout.Space(5.0f);
+                this.DrawInstalledReadouts();
+
+                if (GUILayout.Button("CLOSE EDITOR", this.categoryTitleButtonStyle))
+                {
+                    this.ParentSection.IsEditorVisible = false;
+                }
+
+                GUI.DragWindow();
+            }
+            catch (Exception ex)
+            {
+                Logger.Exception(ex);
+            }
         }
 
         #endregion