using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; using UnityEngine.UI; namespace Bitsplash.DatePicker { [ExecuteInEditMode] public partial class DatePickerContent : MonoBehaviour , IDatePickerSettingsItem { [SerializeField] [HideInInspector] private bool isOpen; const int RowCount = 6; const int ColumnCount = 7; [FormerlySerializedAs("FirstDayOfWeek")] [SerializeField] [Tooltip("the first day of the week for the content")] private DayOfWeek firstDayOfWeek = DayOfWeek.Sunday; [FormerlySerializedAs("RightToLeft")] [SerializeField] private bool rightToLeft = false; [FormerlySerializedAs("BottomToTop")] [SerializeField] private bool bottomToTop = false; [FormerlySerializedAs("CellPrefab")] [SerializeField] [Tooltip("drag a cell template here to use it with the datepicker")] private DatePickerCell cellPrefab = null; [FormerlySerializedAs("SelectionMode")] [SerializeField] [Tooltip("single,range and multiple selection types. ")] private SelectionType selectionMode; [FormerlySerializedAs("AllowEmptySelection")] [SerializeField] private bool allowEmptySelection = false; [SerializeField] private DateTime startDate = new DateTime(1960,1,1); [SerializeField] private DateTime endDate = new DateTime(2030, 12, 31); void ValidateYear() { if (endDate < startDate) endDate = startDate; mMonthFirst = new DateTime(mMonthFirst.Year, mMonthFirst.Month, 1); if(mMonthFirst > endDate) { mMonthFirst = new DateTime(endDate.Year, endDate.Month, 1); } if(mMonthFirst < startDate) { mMonthFirst = new DateTime(startDate.Year, startDate.Month, 1); } } public DateTime StartDate { get { return startDate; } set { startDate = value.Date; ValidateYear(); Invalidate(); OnSettingsChanged(); } } public DateTime EndDate { get { return endDate; } set { endDate = value.Date; ValidateYear(); Invalidate(); OnSettingsChanged(); } } /// /// the first day of the week for the date picker /// public DayOfWeek FirstDayOfWeek { get { return firstDayOfWeek; } set { firstDayOfWeek = value; OnSettingsChanged(); } } /// /// set the date picker to right to left mode /// public bool RightToLeft { get { return rightToLeft; } set { rightToLeft = value; OnSettingsChanged(); } } /// /// show days from bottom to top instead of top to bottom /// public bool BottomToTop { get { return bottomToTop; } set { bottomToTop = value; OnSettingsChanged(); } } //public DatePickerCell CellPrefab //{ // get { return cellPrefab; } // set // { // cellPrefab = value; // } //} /// /// set the selection mode for the date picker. Single ,Range or Multiple /// public SelectionType SelectionMode { get { return selectionMode; } set { selectionMode = value; OnSettingsChanged(); } } /// /// allows selection of the date picker to be empty /// public bool AllowEmptySelection { get { return allowEmptySelection; } set { allowEmptySelection = value; OnSettingsChanged(); } } /// /// used for internal purpose /// public event Action SettingsChanged; /// /// currently the displayed month and year /// DateTime mMonthFirst = DateTime.Today; /// /// genearted cells /// DatePickerCell[] mCells; /// /// the selection collection object for the content /// DatePickerCollection mSelection = new DatePickerCollection(); /// /// a date to cell map for quick lookup /// Dictionary mDateToCell = new Dictionary(); /// /// an input delegation for the date picker /// DatePickerInput mDatePickerInput; /// /// true if the datepicker should be recreated /// bool mInvalidated = true; /// /// This event triggers when the use navigates the datepicker /// public UnityEvent OnDisplayChanged; /// /// this event triggers when the date selection has changed /// public UnityEvent OnSelectionChanged; /// /// the date picker selection collection. Use this object to change and query the current date selection /// public DatePickerCollection Selection { get { return mSelection; } } void EnsureInput() { mDatePickerInput = GetComponent(); if (mDatePickerInput == null) mDatePickerInput = gameObject.AddComponent(); } /// /// the currently displayed date in the datepicker /// public DateTime DisplayDate { get { return mMonthFirst; } } /// /// sets the month and year being displayed in the date picker. /// /// /// public void SetMonthAndYear(int year,int month) { FillCells(new DateTime(year, month, 1)); } /// /// sets the year being displayed in the date picker /// /// public void SetYear(int year) { FillCells(new DateTime(year, mMonthFirst.Month, 1)); } /// /// sets the month being displayed in the date picker /// /// public void SetMonth(int month) { FillCells(new DateTime(mMonthFirst.Year,month, 1)); } /// /// used internally /// public string EditorTitle { get {return "Board"; } } /// /// used internally /// public int Order { get { return 0; } } /// /// advances the display by 1 year /// public void NextYear() { FillCells(mMonthFirst.AddYears(1)); } void OnSettingsChanged() { if (SettingsChanged != null) SettingsChanged(); } /// /// retracts the display by 1 year /// public void PrevYear() { FillCells(mMonthFirst.AddYears(-1)); } /// /// advances the display by 1 month /// public void NextMonth() { FillCells(mMonthFirst.AddMonths(1)); } /// /// retracts the display by 1 month /// public void PrevMonth() { FillCells(mMonthFirst.AddMonths(-1)); } public virtual string DateToString(DateTime date) { return date.Day.ToString(); } void GenerateCells() { Clear(); if (cellPrefab == null) return; mCells = new DatePickerCell[((int)RowCount) * ((int)ColumnCount)]; float ColumnSize = 1f / ColumnCount; float RowSize = 1f / RowCount; for(float i=0; i()); CommonMethods.HideObject(newObj); newObj.name = String.Format("day_{0}_{1}", j, i); newObj.SetActive(true); CommonMethods.EnsureComponent(newObj); var rect = newObj.GetComponent(); rect.anchorMin = new Vector2(startX, startY); rect.anchorMax = new Vector2(endX, endY); rect.anchoredPosition = new Vector2(0f, 0f); rect.sizeDelta = new Vector2(0f, 0f); int childIndex = (int)(i * ColumnCount + j); childIndex = (int)(i * ColumnCount + j); mCells[childIndex] = newObj.GetComponent(); var addon = CommonMethods.EnsureComponent(newObj); addon.SetParent(this, childIndex); } } FillCells(mMonthFirst); } DateTime MonthFromDate(DateTime date) { return new DateTime(date.Year, date.Month, 1); } DatePickerCell getCell(int day,int week) { return mCells[week * ColumnCount + day]; } void FillCells(DateTime monthFirst) { monthFirst = monthFirst.Date; mMonthFirst = monthFirst; ValidateYear(); if (mCells == null) return; monthFirst = mMonthFirst; int monthDayOfWeek = (int)monthFirst.DayOfWeek; int span = monthDayOfWeek - (int)FirstDayOfWeek; if (span < 0) span += 7; DateTime startFrom = (monthFirst - TimeSpan.FromDays(span)).Date; DateTime endIn = startFrom + TimeSpan.FromDays(RowCount * ColumnCount); DateTime monthLast = monthFirst + TimeSpan.FromDays(DateTime.DaysInMonth(monthFirst.Year, monthFirst.Month) - 1); DateTime current = startFrom; mDateToCell.Clear(); for (int i=0; i monthLast || current < startDate || current > endDate) cellenabled = false; mCells[i].SetInitialSettings(cellenabled, false); mDateToCell[current.Date] = mCells[i]; current += TimeSpan.FromDays(1); } RefreshSelection(); if (OnDisplayChanged != null) OnDisplayChanged.Invoke(); } protected void Clear() { IDateTimeItem[] children = GetComponentsInChildren(); for (int i = 0; i < children.Length; ++i) { if (children[i] != null) { if (children[i].gameObject.GetComponentInParent() != this) continue; if (children[i].gameObject != gameObject) CommonMethods.SafeDestroy(children[i].gameObject); } } } public void Invalidate() { mInvalidated = true; } void HookEvents() { ((IDatePickerCollectionPrivate)mSelection).SelectionModified -= DatePicker_SelectionModified; ((IDatePickerCollectionPrivate)mSelection).SelectionModified += DatePicker_SelectionModified; } private void DatePicker_SelectionModified() { RaiseSelectionChanged(); } public void Start() { HookEvents(); EnsureInput(); GenerateCells(); // if (AllowEmptySelection == false) // SelectOne(DateTime.Today); } public void Update() { if(AllowEmptySelection != ((IDatePickerCollectionPrivate)mSelection).AllowEmpty) ((IDatePickerCollectionPrivate)mSelection).AllowEmpty = AllowEmptySelection; UpdateSelection(); if(mInvalidated) { GenerateCells(); mInvalidated = false; } } public void OnValidate() { ValidateYear(); OnSettingsChanged(); Invalidate(); } /// /// retrives the underlaying gameobject specified by dateTime. If the dateTime is not currently displayed , null is returned /// /// /// public DatePickerCell GetCellObjectByDate(DateTime dateTime) { DatePickerCell res = null; if (mDateToCell.TryGetValue(dateTime.Date, out res)) return res; return null; } } }