You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

408 lines
14 KiB

using UnityEngine.Experimental.UIElements;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.PackageManager.UI
{
#if !UNITY_2018_3_OR_NEWER
internal class PackageListFactory : UxmlFactory<PackageList>
{
protected override PackageList DoCreate(IUxmlAttributes bag, CreationContext cc)
{
return new PackageList();
}
}
#endif
internal class PackageList : VisualElement
{
#if UNITY_2018_3_OR_NEWER
internal new class UxmlFactory : UxmlFactory<PackageList> { }
#endif
public event Action<Package> OnSelected = delegate { };
public event Action OnLoaded = delegate { };
public event Action OnFocusChange = delegate { };
private readonly VisualElement root;
internal PackageItem selectedItem;
private List<PackageGroup> Groups;
public PackageList()
{
Groups = new List<PackageGroup>();
root = Resources.GetTemplate("PackageList.uxml");
Add(root);
root.StretchToParentSize();
UIUtils.SetElementDisplay(Empty, false);
UIUtils.SetElementDisplay(NoResult, false);
PackageCollection.Instance.OnPackagesChanged += SetPackages;
RegisterCallback<AttachToPanelEvent>(OnEnterPanel);
RegisterCallback<DetachFromPanelEvent>(OnLeavePanel);
Reload();
}
public void GrabFocus()
{
if (selectedItem == null)
return;
selectedItem.Focus();
}
public void ShowResults(PackageItem item)
{
NoResultText.text = string.Empty;
UIUtils.SetElementDisplay(NoResult, false);
Select(item);
EditorApplication.delayCall += ScrollIfNeeded;
UpdateGroups();
}
public void ShowNoResults()
{
NoResultText.text = string.Format("No results for \"{0}\"", PackageSearchFilter.Instance.SearchText);
UIUtils.SetElementDisplay(NoResult, true);
foreach (var group in Groups)
{
UIUtils.SetElementDisplay(group, false);
}
Select(null);
OnSelected(null);
}
private void UpdateGroups()
{
foreach (var group in Groups)
{
PackageItem firstPackage = null;
PackageItem lastPackage = null;
var listGroup = group.Query<PackageItem>().ToList();
foreach (var item in listGroup)
{
if (!item.visible)
continue;
if (firstPackage == null) firstPackage = item;
lastPackage = item;
}
if (firstPackage == null && lastPackage == null)
{
UIUtils.SetElementDisplay(group, false);
}
else
{
UIUtils.SetElementDisplay(group, true);
group.firstPackage = firstPackage;
group.lastPackage = lastPackage;
}
}
}
private void OnEnterPanel(AttachToPanelEvent e)
{
panel.visualTree.RegisterCallback<KeyDownEvent>(OnKeyDownShortcut);
}
private void OnLeavePanel(DetachFromPanelEvent e)
{
panel.visualTree.UnregisterCallback<KeyDownEvent>(OnKeyDownShortcut);
}
private void ScrollIfNeeded()
{
EditorApplication.delayCall -= ScrollIfNeeded;
if (selectedItem == null)
return;
var minY = List.worldBound.yMin;
var maxY = List.worldBound.yMax;
var itemMinY = selectedItem.worldBound.yMin;
var itemMaxY = selectedItem.worldBound.yMax;
var scroll = List.scrollOffset;
if (itemMinY < minY)
{
scroll.y -= minY - itemMinY;
if (scroll.y <= minY)
scroll.y = 0;
List.scrollOffset = scroll;
}
else if (itemMaxY > maxY)
{
scroll.y += itemMaxY - maxY;
List.scrollOffset = scroll;
}
}
private void OnKeyDownShortcut(KeyDownEvent evt)
{
if (selectedItem == null)
return;
if (evt.keyCode == KeyCode.Tab)
{
OnFocusChange();
evt.StopPropagation();
return;
}
if (evt.keyCode == KeyCode.UpArrow)
{
if (selectedItem.previousItem != null)
{
Select(selectedItem.previousItem);
ScrollIfNeeded();
}
else if (selectedItem.packageGroup.previousGroup != null && selectedItem.packageGroup.previousGroup.visible)
{
Select(selectedItem.packageGroup.previousGroup.lastPackage);
ScrollIfNeeded();
}
evt.StopPropagation();
return;
}
if (evt.keyCode == KeyCode.DownArrow)
{
if (selectedItem.nextItem != null)
{
Select(selectedItem.nextItem);
ScrollIfNeeded();
}
else if (selectedItem.packageGroup.nextGroup != null && selectedItem.packageGroup.nextGroup.visible)
{
Select(selectedItem.packageGroup.nextGroup.firstPackage);
ScrollIfNeeded();
}
evt.StopPropagation();
return;
}
if (evt.keyCode == KeyCode.PageUp)
{
if (selectedItem.packageGroup != null)
{
if (selectedItem == selectedItem.packageGroup.lastPackage && selectedItem != selectedItem.packageGroup.firstPackage)
{
Select(selectedItem.packageGroup.firstPackage);
ScrollIfNeeded();
}
else if (selectedItem == selectedItem.packageGroup.firstPackage && selectedItem.packageGroup.previousGroup != null && selectedItem.packageGroup.previousGroup.visible)
{
Select(selectedItem.packageGroup.previousGroup.lastPackage);
ScrollIfNeeded();
}
else if (selectedItem != selectedItem.packageGroup.lastPackage && selectedItem != selectedItem.packageGroup.firstPackage)
{
Select(selectedItem.packageGroup.firstPackage);
ScrollIfNeeded();
}
}
evt.StopPropagation();
return;
}
if (evt.keyCode == KeyCode.PageDown)
{
if (selectedItem.packageGroup != null)
{
if (selectedItem == selectedItem.packageGroup.firstPackage && selectedItem != selectedItem.packageGroup.lastPackage)
{
Select(selectedItem.packageGroup.lastPackage);
ScrollIfNeeded();
}
else if (selectedItem == selectedItem.packageGroup.lastPackage && selectedItem.packageGroup.nextGroup != null && selectedItem.packageGroup.nextGroup.visible)
{
Select(selectedItem.packageGroup.nextGroup.firstPackage);
ScrollIfNeeded();
}
else if (selectedItem != selectedItem.packageGroup.firstPackage && selectedItem != selectedItem.packageGroup.lastPackage)
{
Select(selectedItem.packageGroup.lastPackage);
ScrollIfNeeded();
}
}
evt.StopPropagation();
}
}
private void Reload()
{
// Force a re-init to initial condition
PackageCollection.Instance.UpdatePackageCollection();
SelectLastSelection();
}
private void ClearAll()
{
List.Clear();
Groups.Clear();
UIUtils.SetElementDisplay(Empty, false);
UIUtils.SetElementDisplay(NoResult, false);
}
private void SetPackages(IEnumerable<Package> packages)
{
if (PackageCollection.Instance.Filter == PackageFilter.Modules)
{
packages = packages.Where(pkg => pkg.IsBuiltIn);
}
else if (PackageCollection.Instance.Filter== PackageFilter.All)
{
packages = packages.Where(pkg => !pkg.IsBuiltIn);
}
else
{
packages = packages.Where(pkg => !pkg.IsBuiltIn);
packages = packages.Where(pkg => pkg.Current != null);
}
OnLoaded();
ClearAll();
var packagesGroup = new PackageGroup(PackageGroupOrigins.Packages.ToString());
Groups.Add(packagesGroup);
List.Add(packagesGroup);
packagesGroup.previousGroup = null;
var builtInGroup = new PackageGroup(PackageGroupOrigins.BuiltInPackages.ToString());
Groups.Add(builtInGroup);
List.Add(builtInGroup);
if ((PackageCollection.Instance.Filter & PackageFilter.Modules) == PackageFilter.Modules)
{
packagesGroup.nextGroup = builtInGroup;
builtInGroup.previousGroup = packagesGroup;
builtInGroup.nextGroup = null;
}
else
{
packagesGroup.nextGroup = null;
UIUtils.SetElementDisplay(builtInGroup, false);
}
var lastSelection = PackageCollection.Instance.SelectedPackage;
Select(null);
PackageItem defaultSelection = null;
foreach (var package in packages.OrderBy(pkg => pkg.Versions.FirstOrDefault() == null ? pkg.Name : pkg.Versions.FirstOrDefault().DisplayName))
{
var item = AddPackage(package);
if (null == selectedItem && defaultSelection == null)
defaultSelection = item;
if (null == selectedItem && !string.IsNullOrEmpty(lastSelection) && package.Name.Equals(lastSelection))
Select(item);
}
if (selectedItem == null)
Select(defaultSelection);
PackageFiltering.FilterPackageList(this);
}
public void SelectLastSelection()
{
var lastSelection = PackageCollection.Instance.SelectedPackage;
if (lastSelection == null)
return;
var list = List.Query<PackageItem>().ToList();
PackageItem defaultSelection = null;
foreach (var item in list)
{
if (defaultSelection == null)
defaultSelection = item;
if (!string.IsNullOrEmpty(lastSelection) && item.package.Name.Equals(lastSelection))
{
defaultSelection = item;
break;
}
}
selectedItem = null;
Select(defaultSelection);
}
private PackageItem AddPackage(Package package)
{
var groupName = package.Latest != null ? package.Latest.Group : package.Current.Group;
var group = GetOrCreateGroup(groupName);
var packageItem = group.AddPackage(package);
packageItem.OnSelected += Select;
return packageItem;
}
private PackageGroup GetOrCreateGroup(string groupName)
{
foreach (var g in Groups)
{
if (g.name == groupName)
return g;
}
var group = new PackageGroup(groupName);
var latestGroup = Groups.LastOrDefault();
Groups.Add(group);
List.Add(group);
group.previousGroup = null;
if (latestGroup != null)
{
latestGroup.nextGroup = group;
group.previousGroup = latestGroup;
group.nextGroup = null;
}
return group;
}
private void Select(PackageItem packageItem)
{
if (packageItem == selectedItem)
return;
var selectedPackageName = packageItem != null ? packageItem.package.Name : null;
PackageCollection.Instance.SelectedPackage = selectedPackageName;
if (selectedItem != null)
selectedItem.SetSelected(false); // Clear Previous selection
selectedItem = packageItem;
if (selectedItem == null)
{
OnSelected(null);
return;
}
selectedItem.SetSelected(true);
ScrollIfNeeded();
OnSelected(selectedItem.package);
}
private ScrollView List { get { return root.Q<ScrollView>("scrollView"); } }
private VisualElement Empty { get { return root.Q<VisualElement>("emptyArea"); } }
private VisualElement NoResult { get { return root.Q<VisualElement>("noResult"); } }
private Label NoResultText { get { return root.Q<Label>("noResultText"); } }
}
}