context: // Copyright (c) Rotorz Limited. All rights reserved.
  // Licensed under the MIT license. See LICENSE file in the project root.
  
  using System.Collections.Generic;
  using UnityEditor;
  using UnityEngine;
  
  namespace Chronos.ReorderableList {
  
  	/// <summary>
  	/// Utility class for drawing reorderable lists.
  	/// </summary>
  	public static class ReorderableListGUI {
  
  		/// <summary>
  		/// Default list item height is 18 pixels.
  		/// </summary>
  		public const float DefaultItemHeight = 18;
  
  		/// <summary>
  		/// Gets or sets the zero-based index of the last item that was changed. A value of -1
  		/// indicates that no item was changed by list.
  		/// </summary>
  		/// <remarks>
  		/// <para>This property should not be set when items are added or removed.</para>
  		/// </remarks>
  		public static int IndexOfChangedItem { get; internal set; }
  
  		/// <summary>
  		/// Gets the control ID of the list that is currently being drawn.
  		/// </summary>
  		public static int CurrentListControlID {
  			get { return ReorderableListControl.CurrentListControlID; }
  		}
  
  		/// <summary>
  		/// Gets the position of the list control that is currently being drawn.
  		/// </summary>
  		/// <remarks>
  		/// <para>The value of this property should be ignored for <see cref="EventType.Layout"/>
  		/// type events when using reorderable list controls with automatic layout.</para>
  		/// </remarks>
  		/// <see cref="CurrentItemTotalPosition"/>
  		public static Rect CurrentListPosition {
  			get { return ReorderableListControl.CurrentListPosition; }
  		}
  
  		/// <summary>
  		/// Gets the zero-based index of the list item that is currently being drawn;
  		/// or a value of -1 if no item is currently being drawn.
  		/// </summary>
  		public static int CurrentItemIndex {
  			get { return ReorderableListControl.CurrentItemIndex; }
  		}
  
  		/// <summary>
  		/// Gets the total position of the list item that is currently being drawn.
  		/// </summary>
  		/// <remarks>
  		/// <para>The value of this property should be ignored for <see cref="EventType.Layout"/>
  		/// type events when using reorderable list controls with automatic layout.</para>
  		/// </remarks>
  		/// <see cref="CurrentItemIndex"/>
  		/// <see cref="CurrentListPosition"/>
  		public static Rect CurrentItemTotalPosition {
  			get { return ReorderableListControl.CurrentItemTotalPosition; }
  		}
  
  		#region Basic Item Drawers
  
  		/// <summary>
  		/// Default list item drawer implementation.
  		/// </summary>
  		/// <remarks>
  		/// <para>Always presents the label "Item drawer not implemented.".</para>
  		/// </remarks>
  		/// <param name="position">Position to draw list item control(s).</param>
  		/// <param name="item">Value of list item.</param>
  		/// <returns>
  		/// Unmodified value of list item.
  		/// </returns>
  		/// <typeparam name="T">Type of list item.</typeparam>
  		public static T DefaultItemDrawer<T>(Rect position, T item) {
  			GUI.Label(position, "Item drawer not implemented.");
  			return item;
  		}
  
  		/// <summary>
  		/// Draws text field allowing list items to be edited.
  		/// </summary>
  		/// <remarks>
  		/// <para>Null values are automatically changed to empty strings since null
  		/// values cannot be edited using a text field.</para>
  		/// <para>Value of <c>GUI.changed</c> is set to <c>true</c> if value of item
  		/// is modified.</para>
  		/// </remarks>
  		/// <param name="position">Position to draw list item control(s).</param>
  		/// <param name="item">Value of list item.</param>
  		/// <returns>
  		/// Modified value of list item.
  		/// </returns>
  		public static string TextFieldItemDrawer(Rect position, string item) {
  			if (item == null) {
  				item = "";
  				GUI.changed = true;
  			}
  			return EditorGUI.TextField(position, item);
  		}
  
  		#endregion
  
  		/// <summary>
  		/// Gets the default list control implementation.
  		/// </summary>
  		private static ReorderableListControl DefaultListControl { get; set; }
  
  		static ReorderableListGUI() {
  			DefaultListControl = new ReorderableListControl();
  
  			// Duplicate default styles to prevent user scripts from interferring with
  			// the default list control instance.
  			DefaultListControl.ContainerStyle = new GUIStyle(ReorderableListStyles.Container);
  			DefaultListControl.FooterButtonStyle = new GUIStyle(ReorderableListStyles.FooterButton);
  			DefaultListControl.ItemButtonStyle = new GUIStyle(ReorderableListStyles.ItemButton);
  
  			IndexOfChangedItem = -1;
  		}
  
  		private static GUIContent s_Temp = new GUIContent();
  
  		#region Title Control
  
  		/// <summary>
  		/// Draw title control for list field.
  		/// </summary>
  		/// <remarks>
  		/// <para>When needed, should be shown immediately before list field.</para>
  		/// </remarks>
  		/// <example>
  		/// <code language="csharp"><![CDATA[
  		/// ReorderableListGUI.Title(titleContent);
  		/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer);
  		/// ]]></code>
  		/// <code language="unityscript"><![CDATA[
  		/// ReorderableListGUI.Title(titleContent);
  		/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer);
  		/// ]]></code>
  		/// </example>
  		/// <param name="title">Content for title control.</param>
  		public static void Title(GUIContent title) {
  			Rect position = GUILayoutUtility.GetRect(title, ReorderableListStyles.Title);
  			position.height += 6;
  			Title(position, title);
  		}
  
  		/// <summary>
  		/// Draw title control for list field.
  		/// </summary>
  		/// <remarks>
  		/// <para>When needed, should be shown immediately before list field.</para>
  		/// </remarks>
  		/// <example>
  		/// <code language="csharp"><![CDATA[
  		/// ReorderableListGUI.Title("Your Title");
  		/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer);
  		/// ]]></code>
  		/// <code language="unityscript"><![CDATA[
  		/// ReorderableListGUI.Title('Your Title');
  		/// ReorderableListGUI.ListField(list, DynamicListGU.TextFieldItemDrawer);
  		/// ]]></code>
  		/// </example>
  		/// <param name="title">Text for title control.</param>
  		public static void Title(string title) {
  			s_Temp.text = title;
  			Title(s_Temp);
  		}
  
  		/// <summary>
  		/// Draw title control for list field with absolute positioning.
  		/// </summary>
  		/// <param name="position">Position of control.</param>
  		/// <param name="title">Content for title control.</param>
  		public static void Title(Rect position, GUIContent title) {
  			if (Event.current.type == EventType.Repaint)
  				ReorderableListStyles.Title.Draw(position, title, false, false, false, false);
  		}
  
  		/// <summary>
  		/// Draw title control for list field with absolute positioning.
  		/// </summary>
  		/// <param name="position">Position of control.</param>
  		/// <param name="text">Text for title control.</param>
  		public static void Title(Rect position, string text) {
  			s_Temp.text = text;
  			Title(position, s_Temp);
  		}
  
  		#endregion
  
  		#region List<T> Control
  
  		/// <summary>
  		/// Draw list field control.
  		/// </summary>
  		/// <param name="list">The list which can be reordered.</param>
  		/// <param name="drawItem">Callback to draw list item.</param>
  		/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param>
  		/// <param name="itemHeight">Height of a single list item.</param>
  		/// <param name="flags">Optional flags to pass into list field.</param>
  		/// <typeparam name="T">Type of list item.</typeparam>
  		private static void DoListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) {
  			var adaptor = new GenericListAdaptor<T>(list, drawItem, itemHeight);
  			ReorderableListControl.DrawControlFromState(adaptor, drawEmpty, flags);
  		}
  		/// <summary>
  		/// Draw list field control with absolute positioning.
  		/// </summary>
  		/// <param name="position">Position of control.</param>
  		/// <param name="list">The list which can be reordered.</param>
  		/// <param name="drawItem">Callback to draw list item.</param>
  		/// <param name="drawEmpty">Callback to draw custom content for empty list (optional).</param>
  		/// <param name="itemHeight">Height of a single list item.</param>
  		/// <param name="flags">Optional flags to pass into list field.</param>
  		/// <typeparam name="T">Type of list item.</typeparam>
  		private static void DoListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) {
  			var adaptor = new GenericListAdaptor<T>(list, drawItem, itemHeight);
  			ReorderableListControl.DrawControlFromState(position, adaptor, drawEmpty, flags);
  		}
  
  
  		/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/>
  		public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight, ReorderableListFlags flags) {
  			DoListField<T>(list, drawItem, drawEmpty, itemHeight, flags);
  		}
  		/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/>
  		public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight, ReorderableListFlags flags) {
  			DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, itemHeight, flags);
  		}
  
  
  		/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/>
  		public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, float itemHeight) {
  			DoListField<T>(list, drawItem, drawEmpty, itemHeight, 0);
  		}
  		/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/>
  		public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, float itemHeight) {
  			DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, itemHeight, 0);
  		}
  
  
  		/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/>
  		public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty, ReorderableListFlags flags) {
  			DoListField<T>(list, drawItem, drawEmpty, DefaultItemHeight, flags);
  		}
  		/// <inheritdoc cref="DoListFieldAbsolute{T}(Rect, IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmptyAbsolute, float, ReorderableListFlags)"/>
  		public static void ListFieldAbsolute<T>(Rect position, IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmptyAbsolute drawEmpty, ReorderableListFlags flags) {
  			DoListFieldAbsolute<T>(position, list, drawItem, drawEmpty, DefaultItemHeight, flags);
  		}
  
  
  		/// <inheritdoc cref="DoListField{T}(IList{T}, ReorderableListControl.ItemDrawer{T}, ReorderableListControl.DrawEmpty, float, ReorderableListFlags)"/>
  		public static void ListField<T>(IList<T> list, ReorderableListControl.ItemDrawer<T> drawItem, ReorderableListControl.DrawEmpty drawEmpty) {
  
gt: 			DoListField<T>(list, drawItem, drawEmpty, DefaultItemHeight, 0);