123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- using System;
- using System.Collections.Generic;
- using JetBrains.Annotations;
- using Unity.Cloud.Collaborate.Assets;
- using Unity.Cloud.Collaborate.Views.Adapters.ListAdapters;
- using Unity.Cloud.Collaborate.Components;
- using Unity.Cloud.Collaborate.Models.Structures;
- using Unity.Cloud.Collaborate.Presenters;
- using Unity.Cloud.Collaborate.UserInterface;
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.Assertions;
- using UnityEngine.UIElements;
- namespace Unity.Cloud.Collaborate.Views
- {
- [UsedImplicitly]
- internal class ChangesTabPageView : TabPageComponent, IChangesView
- {
- [CanBeNull]
- IChangesPresenter m_Presenter;
- public const string UssClassName = "changes-tab-page-view";
- public const string SearchBarUssClassName = UssClassName + "__search-bar";
- public const string EntryGroupsUssClassName = UssClassName + "__entry-groups";
- public const string PublishButtonUssClassName = UssClassName + "__publish-button";
- public const string TextFieldUssClassName = UssClassName + "__text-field";
- public const string ListViewUssClassName = UssClassName + "__list-view";
- static readonly string k_LayoutPath = $"{CollaborateWindow.LayoutPath}/{nameof(ChangesTabPageView)}.uxml";
- static readonly string k_StylePath = $"{CollaborateWindow.StylePath}/{nameof(ChangesTabPageView)}.uss";
- readonly IconTextButton m_PublishButton;
- readonly BetterTextField m_RevisionSummaryBox;
- readonly SearchBar m_SearchBar;
- readonly VisualElement m_EntryGroupsContainer;
- bool m_Active;
- [CanBeNull]
- ConflictedChangeListAdapter m_ConflictedChangeListAdapter;
- [CanBeNull]
- ToggleableChangeListAdapter m_ToggleableChangeListAdapter;
- [CanBeNull]
- ChangeEntryGroup m_EntryToggleableGroup;
- [CanBeNull]
- ChangeEntryGroup m_EntryConflictsGroup;
- [CanBeNull]
- VisualElement m_ActiveGroup;
- public ChangesTabPageView()
- {
- AddToClassList(UssClassName);
- AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(k_LayoutPath).CloneTree(this);
- styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>(k_StylePath));
- // Get the components defined in the style / layout files.
- m_SearchBar = this.Q<SearchBar>(className: SearchBarUssClassName);
- m_RevisionSummaryBox = this.Q<BetterTextField>(className: TextFieldUssClassName);
- m_PublishButton = this.Q<IconTextButton>(className: PublishButtonUssClassName);
- m_EntryGroupsContainer = this.Q<VisualElement>(className: EntryGroupsUssClassName);
- // Initialize the text strings.
- m_PublishButton.Text = StringAssets.publishButton;
- m_RevisionSummaryBox.Placeholder = StringAssets.publishSummaryPlaceholder;
- }
- /// <inheritdoc />
- public IChangesPresenter Presenter
- {
- set
- {
- m_Presenter = value;
- SetupEvents();
- // If tab active before presenter has been added, call start once we have it.
- if (Active)
- {
- value.Start();
- }
- }
- }
- /// <summary>
- /// Setup events to communicate with the presenter. Must be called after presenter is set.
- /// </summary>
- void SetupEvents()
- {
- Assert.IsNotNull(m_Presenter, "Invalid changes page state.");
- // Set up publish invocation.
- m_PublishButton.Clicked += m_Presenter.RequestPublish;
- // Send text values to the presenter.
- m_SearchBar.Search += m_Presenter.SetSearchQuery;
- m_RevisionSummaryBox.OnValueChangedHandler += s => m_Presenter.SetRevisionSummary(s);
- }
- /// <inheritdoc />
- public void SetBusyStatus(bool busy)
- {
- m_EntryGroupsContainer.SetEnabled(!busy);
- m_RevisionSummaryBox.SetEnabled(!busy);
- }
- /// <inheritdoc />
- protected override void SetActive()
- {
- Assert.IsFalse(m_Active, "The view is already active.");
- m_Active = true;
- m_Presenter?.Start();
- }
- /// <inheritdoc />
- protected override void SetInactive()
- {
- Assert.IsTrue(m_Active, "The view is already inactive.");
- m_Active = false;
- m_Presenter?.Stop();
- }
- /// <inheritdoc />
- public void SetSearchQuery(string query)
- {
- Assert.IsNotNull(m_Presenter, "Invalid state when setting search query.");
- m_SearchBar.SetValueWithoutNotify(query);
- var isSearching = m_Presenter.Searching;
- if (m_EntryConflictsGroup != null) m_EntryConflictsGroup.Searching = isSearching;
- if (m_EntryToggleableGroup != null) m_EntryToggleableGroup.Searching = isSearching;
- }
- /// <inheritdoc />
- public void SetRevisionSummary(string message)
- {
- m_RevisionSummaryBox.SetValueWithoutNotify(message);
- }
- /// <inheritdoc />
- public void SetConflicts(IReadOnlyList<IChangeEntryData> list)
- {
- Assert.IsNotNull(m_Presenter, "Invalid state while creating conflict list.");
- // Initialise conflicts group
- if (m_EntryConflictsGroup == null)
- {
- var conflictsList = new AdapterListView { name = StringAssets.changeListConflictedList, SelectionType = SelectionType.None };
- conflictsList.AddToClassList(ListViewUssClassName);
- m_ConflictedChangeListAdapter = new ConflictedChangeListAdapter(m_Presenter);
- conflictsList.SetAdapter(m_ConflictedChangeListAdapter);
- m_EntryConflictsGroup = new ChangeEntryGroup(conflictsList) { Title = StringAssets.changeListConflictedHeader };
- m_EntryConflictsGroup.SetOverflowCallback(m_Presenter.OnClickConflictGroupOverflow);
- m_EntryConflictsGroup.Searching = m_Presenter.Searching;
- }
- Assert.IsTrue(m_ConflictedChangeListAdapter != null && m_EntryConflictsGroup != null, "Invalid state while setting conflicted list.");
- // Ensure conflict list is displayed
- if (m_ActiveGroup != m_EntryConflictsGroup)
- {
- m_ActiveGroup?.RemoveFromHierarchy();
- m_EntryGroupsContainer.Add(m_EntryConflictsGroup);
- m_ActiveGroup = m_EntryConflictsGroup;
- }
- m_ConflictedChangeListAdapter.List = list;
- var count = m_Presenter.ConflictedCount;
- m_EntryConflictsGroup.NumberMenuItems = m_Presenter.ConflictGroupOverflowEntryCount;
- m_EntryConflictsGroup.SelectedEntryCount = count;
- m_EntryConflictsGroup.EntryCount = count;
- }
- /// <inheritdoc />
- public void SetSelectedChanges()
- {
- Assert.IsNotNull(m_Presenter, "Invalid state while setting selected items from toggleable list.");
- if(m_ToggleableChangeListAdapter == null)
- {
- // we might be Selecting partial changes before the view loads the first time,
- // so we just ignore it ....
- return;
- }
-
- Assert.IsTrue(m_ToggleableChangeListAdapter != null && m_EntryToggleableGroup != null, "Invalid state while setting selected items in toggleable list");
- var scrollToIndex = m_ToggleableChangeListAdapter.GetFirstToggledIndex();
- m_ToggleableChangeListAdapter.NotifyDataSetChanged();
- if (scrollToIndex != -1)
- {
- scrollToIndex = Math.Min(scrollToIndex, m_ToggleableChangeListAdapter.GetEntryCount() - 1);
- m_EntryToggleableGroup.ScrollTo(scrollToIndex);
- if(m_ToggleableChangeListAdapter.GetLastBoundElementIndex() < scrollToIndex + 3)
- {
- // the pool of the list is 14 elements .. but the list actually shows only 12 ..
- // so the normal scrollTo call of the list view may stop 1 element short of the selected
- // index if the scrolled to index is greater than the currently selected index.
- m_EntryToggleableGroup.ScrollTo(scrollToIndex + 3);
- }
- }
- }
- /// <inheritdoc />
- public void SetChanges(IReadOnlyList<IChangeEntryData> list)
- {
- Assert.IsNotNull(m_Presenter, "Invalid state while creating toggleable list.");
- // Initialise the toggleable list if not already initialised.
- if (m_EntryToggleableGroup == null)
- {
- var toggleableListView = new AdapterListView { SelectionType = SelectionType.None };
- toggleableListView.AddToClassList(ListViewUssClassName);
- m_ToggleableChangeListAdapter = new ToggleableChangeListAdapter(m_Presenter);
- toggleableListView.SetAdapter(m_ToggleableChangeListAdapter);
- m_EntryToggleableGroup = new ChangeEntryGroup(toggleableListView)
- { Title = StringAssets.changeListFullHeader };
- m_EntryToggleableGroup.SetOverflowCallback(m_Presenter.OnClickGroupOverflow);
- m_EntryToggleableGroup.Searching = m_Presenter.Searching;
- }
- Assert.IsTrue(m_ToggleableChangeListAdapter != null && m_EntryToggleableGroup != null, "Invalid state while setting toggleable list");
- // Ensure single list is displayed
- if (m_ActiveGroup != m_EntryToggleableGroup)
- {
- m_ActiveGroup?.RemoveFromHierarchy();
- m_EntryGroupsContainer.Add(m_EntryToggleableGroup);
- m_ActiveGroup = m_EntryToggleableGroup;
- }
- // Can use list.Count here since searching hides "All".
- m_EntryToggleableGroup.EntryCount = m_Presenter.Searching ? list.Count : m_Presenter.TotalCount;
- m_ToggleableChangeListAdapter.List = list;
- m_EntryToggleableGroup.NumberMenuItems = m_Presenter.GroupOverflowEntryCount;
- m_EntryToggleableGroup.SelectedEntryCount = m_Presenter.ToggledCount;
- }
- /// <inheritdoc />
- public void SetToggledCount(int count)
- {
- if (m_EntryToggleableGroup != null)
- {
- m_EntryToggleableGroup.SelectedEntryCount = count;
- }
- }
- /// <inheritdoc />
- public void SetPublishEnabled(bool enabled, string reason = null)
- {
- m_PublishButton.SetEnabled(enabled);
- // Disabled elements cannot have a tooltip so apply to a empty/dummy parent instead.
- m_PublishButton.parent.tooltip = reason;
- }
- /// <inheritdoc />
- public bool DisplayDialogue(string title, string message, string affirmative)
- {
- return EditorUtility.DisplayDialog(title, message, affirmative);
- }
- /// <inheritdoc />
- public bool DisplayDialogue(string title, string message, string affirmative, string negative)
- {
- return EditorUtility.DisplayDialog(title, message, affirmative, negative);
- }
- [UsedImplicitly]
- public new class UxmlFactory : UxmlFactory<ChangesTabPageView> { }
- }
- }
|