// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Standard Library using System.Collections.Generic; // Unity using UnityEditor.IMGUI.Controls; using UnityEngine; namespace AWS.GameKit.Editor.Windows.Settings { /// /// A GUI element which displays a navigable "table of contents" for the AWS GameKit Settings window in a collapsible tree format. /// public sealed class NavigationTreeWidget : TreeView { public delegate void OnSingleClickedPage(Page selectedPage); private readonly OnSingleClickedPage _onSingleClickedPageCallback; private TreeViewItem _rootItem; private List _treeViewItems; private readonly Dictionary _pageToItemIdMap = new Dictionary(); /// /// Create a new NavigationTreeWidget. /// /// All of the pages that can be navigated to. /// The state to restore from. For example, which item was last selected, which items are collapsed/expanded, etc. /// True if the treeViewState parameter is restoring the tree view from a saved state. False if the treeViewState is a new/default object. /// A callback function to invoke each time an item is single clicked. public NavigationTreeWidget(AllPages allPages, TreeViewState treeViewState, bool isBeingRestored, OnSingleClickedPage onSingleClickedPageCallback) : base(treeViewState) { _onSingleClickedPageCallback = onSingleClickedPageCallback; BuildTreeViewItems(allPages); Reload(); if (isBeingRestored) { // Restore the last selected element IList selectedIds = GetSelection(); SetSelection(selectedIds, TreeViewSelectionOptions.FireSelectionChanged); if (selectedIds.Count > 0) { // There should be exactly one item selected because CanMultiSelect() returns false, so select that item here: SingleClickedItem(selectedIds[0]); } } else { // Set the default initial view ExpandAll(); // Select the first item int startingPageId = 1; ClickItem(startingPageId); } } /// /// Simulate a mouse click on the page's item in the tree view. /// public void ClickItem(Page page) { int itemId; if (!_pageToItemIdMap.TryGetValue(page, out itemId)) { Debug.LogWarning($"There is no TreeViewItem corresponding to the pageType: {page}. Selecting the first page instead."); itemId = 1; } ClickItem(itemId); } protected override TreeViewItem BuildRoot() { SetupParentsAndChildrenFromDepths(_rootItem, _treeViewItems); return _rootItem; } protected override bool CanMultiSelect(TreeViewItem item) { return false; } /// /// Draw the row's text on the screen. This method is called once per visible row. /// protected override void RowGUI(RowGUIArgs args) { rowHeight = SettingsGUIStyles.NavigationTree.RowHeight; float indent = GetContentIndent(args.item); GUIStyle style = new GUIStyle(SettingsGUIStyles.NavigationTree.RowText) { contentOffset = new Vector2(indent, 0) }; GUI.Label(args.rowRect, args.label, style); } /// /// This callback function is invoked whenever an item is clicked in the tree view. /// protected override void SingleClickedItem(int selectedId) { base.SingleClickedItem(selectedId); // Invoke callback delegate with the clicked-on page NavigationTreeItem selectedItem = (NavigationTreeItem)FindItem(selectedId, _rootItem); _onSingleClickedPageCallback(selectedItem.Page); } /// /// Simulate a mouse click on the specified item in the tree view. /// private void ClickItem(int itemId) { // Highlight the clicked-on row FrameItem(itemId); SetSelection(new List { itemId }, TreeViewSelectionOptions.FireSelectionChanged); // Invoke the callback delegate SingleClickedItem(itemId); } /// /// Define the order in which the pages are displayed in the collapsible navigation tree. /// private void BuildTreeViewItems(AllPages allPages) { int id = 0; _rootItem = new TreeViewItem { id = id, depth = -1, displayName = "Root" }; _treeViewItems = new List() { // Before features: new NavigationTreeItem(++id, 0, allPages.EnvironmentAndCredentialsPage), new NavigationTreeItem(++id, 0, allPages.AllFeaturesPage), // Features: new NavigationTreeItem(++id, 1, allPages.IdentityAndAuthenticationPage), new NavigationTreeItem(++id, 1, allPages.GameStateCloudSavingPage), new NavigationTreeItem(++id, 1, allPages.AchievementsPage), new NavigationTreeItem(++id, 1, allPages.UserGameplayDataPage), // After features: new NavigationTreeItem(++id, 0, allPages.LogPage), }; foreach (TreeViewItem item in _treeViewItems) { NavigationTreeItem navigationItem = (NavigationTreeItem)item; _pageToItemIdMap.Add(navigationItem.Page, navigationItem.id); } } } }