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;
}
}
}