using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Codice.Client.Common;
using Codice.CM.Common;
using PlasticGui;
using PlasticGui.WorkspaceWindow.Locks;
using Unity.PlasticSCM.Editor.UI;
using Unity.PlasticSCM.Editor.UI.Tree;
#if UNITY_6000_2_OR_NEWER
using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem<int>;
#endif
namespace Unity.PlasticSCM.Editor.Views.Locks
{
internal sealed class LocksListView :
PlasticTreeView,
FillLocksTable.IShowContentView,
FillLocksTable.ILocksList
{
internal GenericMenu Menu { get { return mMenu.Menu; } }
internal string EmptyStateMessage { get { return mEmptyStatePanel.Text; } }
internal LocksListView(
WorkspaceInfo wkInfo,
RepositorySpec repSpec,
LocksListHeaderState headerState,
List<string> columnNames,
LocksViewMenu menu,
Action delayedSelectionChangedAction,
Action<IEnumerable<LockInfo>> afterItemsChangedAction,
Action repaintAction)
{
mWkInfo = wkInfo;
mRepSpec = repSpec;
mColumnNames = columnNames;
mMenu = menu;
mDelayedSelectionChangedAction = delayedSelectionChangedAction;
mAfterItemsChangedAction = afterItemsChangedAction;
mEmptyStatePanel = new EmptyStatePanel(repaintAction);
mMultiLinkLabelData = new MultiLinkLabelData(
PlasticLocalization.Name.LocksTutorialLabel.GetString(),
new List<string> { PlasticLocalization.Name.LocksTutorialButton.GetString() },
new List<Action> { () => { Codice.Utils.OpenBrowser.TryOpen(LOCKS_TUTORIAL_LINK); } });
mLocksSelector = new LocksSelector(this, mListViewItemIds);
mDelayedFilterAction = new DelayedActionBySecondsRunner(
DelayedSearchChanged, UnityConstants.SEARCH_DELAYED_INPUT_ACTION_INTERVAL);
mDelayedSelectionRunner = new DelayedActionBySecondsRunner(
DelayedSelectionChanged, UnityConstants.SELECTION_DELAYED_INPUT_ACTION_INTERVAL);
SetupTreeView(headerState);
}
public override void OnGUI(Rect rect)
{
base.OnGUI(rect);
if (Event.current.type == EventType.Layout)
mShouldShowEmptyState = mRows.Count == 0 && !mEmptyStatePanel.IsEmpty();
if (mShouldShowEmptyState)
mEmptyStatePanel.OnGUI(rect);
if (!HasKeyboardFocus())
return;
Event e = Event.current;
if (e.type != EventType.KeyDown)
return;
bool isProcessed = mMenu.ProcessKeyActionIfNeeded(e);
if (isProcessed)
e.Use();
}
protected override IList<TreeViewItem> BuildRows(
TreeViewItem rootItem)
{
if (mLocksList == null)
{
ClearRows(rootItem, mRows);
return mRows;
}
RegenerateRows(
mListViewItemIds,
mLocksList,
rootItem,
mRows);
return mRows;
}
protected override void SearchChanged(string newSearch)
{
mDelayedFilterAction.Run();
}
protected override void SelectionChanged(IList<int> selectedIds)
{
mDelayedSelectionRunner.Run();
}
protected override void ContextClickedItem(int id)
{
mMenu.Popup();
Repaint();
}
protected override void RowGUI(RowGUIArgs args)
{
if (args.item is LocksListViewItem)
{
LocksListViewItemGUI(
mRepSpec,
mWkInfo.ClientPath,
rowHeight,
((LocksListViewItem)args.item).LockInfo,
args,
Repaint);
return;
}
base.RowGUI(args);
}
internal void OnDisable()
{
TreeHeaderSettings.Save(
multiColumnHeader.state,
UnityConstants.LOCKS_TABLE_SETTINGS_NAME);
}
internal List<LockInfo> GetSelectedLocks()
{
return mLocksSelector.GetSelectedLocks();
}
void FillLocksTable.IShowContentView.ShowContentPanel()
{
mEmptyStatePanel.UpdateContent(
string.Empty,
multiLinkLabelData: mMultiLinkLabelData);
Reload();
mLocksSelector.RestoreSelectedLocks();
}
void FillLocksTable.IShowContentView.ShowEmptyStatePanel(string explanationText)
{
mEmptyStatePanel.UpdateContent(
explanationText,
multiLinkLabelData: string.IsNullOrEmpty(searchString) ? mMultiLinkLabelData : null);
Reload();
}
void FillLocksTable.IShowContentView.ShowErrorPanel(string errorText)
{
Debug.LogErrorFormat(
PlasticLocalization.Name.LoadLocksErrorExplanation.GetString(),
errorText);
mEmptyStatePanel.UpdateContent(
PlasticLocalization.Name.LoadLocksError.GetString(),
multiLinkLabelData: mMultiLinkLabelData);
mLocksList = null;
mListViewItemIds.Clear();
Reload();
}
void FillLocksTable.ILocksList.Fill(LockInfoList lockInfoList, Filter filter)
{
mLocksSelector.SaveSelectedLocks();
mListViewItemIds.Clear();
mLocksList = lockInfoList;
Filter();
Sort();
}
void Filter()
{
if (mLocksList == null)
return;
mLocksList.Filter(new Filter(searchString));
mAfterItemsChangedAction(mLocksList.GetLocks());
}
void Sort()
{
if (mLocksList == null)
return;
int sortedColumnIdx = multiColumnHeader.state.sortedColumnIndex;
bool sortAscending = multiColumnHeader.IsSortedAscending(sortedColumnIdx);
mLocksList.Sort(mColumnNames[sortedColumnIdx], sortAscending);
}
void DelayedSearchChanged()
{
Filter();
Reload();
TableViewOperations.ScrollToSelection(this);
}
void DelayedSelectionChanged()
{
mDelayedSelectionChangedAction();
}
void SortingChanged(MultiColumnHeader header)
{
Sort();
Reload();
}
void SetupTreeView(LocksListHeaderState headerState)
{
TreeHeaderSettings.Load(
headerState,
UnityConstants.LOCKS_TABLE_SETTINGS_NAME,
(int)LocksListColumn.ModificationDate,
false);
multiColumnHeader = new MultiColumnHeader(headerState);
multiColumnHeader.canSort = true;
multiColumnHeader.sortingChanged += SortingChanged;
}
static void RegenerateRows(
ListViewItemIds<LockInfo> listViewItemIds,
LockInfoList locksList,
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
ClearRows(rootItem, rows);
if (locksList == null)
return;
foreach (LockInfo lockInfo in locksList.GetLocks())
{
int objectId;
if (!listViewItemIds.TryGetInfoItemId(lockInfo, out objectId))
objectId = listViewItemIds.AddInfoItem(lockInfo);
LocksListViewItem lockListViewItem =
new LocksListViewItem(objectId, lockInfo);
rootItem.AddChild(lockListViewItem);
rows.Add(lockListViewItem);
}
}
static void ClearRows(
TreeViewItem rootItem,
List<TreeViewItem> rows)
{
if (rootItem.hasChildren)
rootItem.children.Clear();
rows.Clear();
}
static void LocksListViewItemGUI(
RepositorySpec repSpec,
string wkPath,
float rowHeight,
LockInfo item,
RowGUIArgs args,
Action avatarLoadedAction)
{
for (var visibleColumnIdx = 0; visibleColumnIdx < args.GetNumVisibleColumns(); visibleColumnIdx++)
{
var cellRect = args.GetCellRect(visibleColumnIdx);
if (visibleColumnIdx == 0)
{
cellRect.x += UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT;
cellRect.width -= UnityConstants.FIRST_COLUMN_WITHOUT_ICON_INDENT;
}
var column = (LocksListColumn) args.GetColumn(visibleColumnIdx);
DrawLocksListViewItem.ForCell(
repSpec,
wkPath,
cellRect,
rowHeight,
item,
column,
avatarLoadedAction,
args.selected,
args.focused);
}
}
bool mShouldShowEmptyState;
ListViewItemIds<LockInfo> mListViewItemIds = new ListViewItemIds<LockInfo>();
LockInfoList mLocksList;
readonly EmptyStatePanel mEmptyStatePanel;
readonly MultiLinkLabelData mMultiLinkLabelData;
readonly DelayedActionBySecondsRunner mDelayedFilterAction;
readonly DelayedActionBySecondsRunner mDelayedSelectionRunner;
readonly LocksSelector mLocksSelector;
readonly Action mDelayedSelectionChangedAction;
readonly Action<IEnumerable<LockInfo>> mAfterItemsChangedAction;
readonly LocksViewMenu mMenu;
readonly List<string> mColumnNames;
readonly RepositorySpec mRepSpec;
readonly WorkspaceInfo mWkInfo;
const string LOCKS_TUTORIAL_LINK = "https://learn.unity.com/tutorial/6650a6abedbc2a2ccccb05a4";
}
}