using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEditor; using Unity.PlasticSCM.Editor.UI; namespace Unity.PlasticSCM.Editor.CloudDrive.Workspaces.DirectoryContent { internal static class ProcessItemsGridViewEvent { internal const int VERTICAL_SCROLL_STEP = 20; internal static bool IfNeeded( Event e, DirectoryContentPanelMenu menu, IItemsGridView itemsGridView, IDragAndDrop dragAndDrop, EditorWindow parentWindow, Action doubleClickAction, Action navigateBackAction, List selectedItemsIndexes, Rect rect, Vector2 itemSize, float scrollPosition, int columnsCount, int itemsCount, bool hasFocus, bool isScrollbarVisible, bool isDragAvailable) { if (isScrollbarVisible && ProcessScrollWheelIfNeeded(e, itemsGridView, scrollPosition)) return true; if (ProcessMouseClickIfNeeded( e, menu, itemsGridView, doubleClickAction, selectedItemsIndexes, rect, itemSize, scrollPosition, columnsCount, itemsCount, isScrollbarVisible)) return true; if (hasFocus && ProcessKeyDownIfNeeded( e, menu, itemsGridView, navigateBackAction, selectedItemsIndexes, columnsCount, itemsCount)) return true; if (ProcessMouseDragIfNeeded( e, itemsGridView, dragAndDrop, parentWindow, rect, itemSize, scrollPosition, columnsCount, itemsCount, isScrollbarVisible, isDragAvailable)) return true; return false; } static bool ProcessScrollWheelIfNeeded( Event e, IItemsGridView itemsGridView, float scrollPosition) { if (e.type != EventType.ScrollWheel) return false; itemsGridView.UpdateScrollPosition( scrollPosition + e.delta.y * VERTICAL_SCROLL_STEP); return true; } static bool ProcessMouseClickIfNeeded( Event e, DirectoryContentPanelMenu menu, IItemsGridView itemsGridView, Action doubleClickAction, List selectedItemsIndexes, Rect rect, Vector2 itemSize, float scrollPosition, int columnsCount, int itemsCount, bool isScrollbarVisible) { if (e.type != EventType.MouseDown && e.type != EventType.MouseUp) return false; Vector2 mousePosition = e.mousePosition - rect.position; if (!ItemsPosition.IsMousePositionInsideGrid( mousePosition, rect, isScrollbarVisible)) { return false; } int itemIndexToSelect = ItemsPosition.GetItemIndexFromMousePosition( mousePosition, itemSize, scrollPosition, columnsCount, itemsCount); bool shouldUpdateSelection = ShouldUpdateSelection( selectedItemsIndexes.Contains(itemIndexToSelect), Keyboard.HasControlOrCommandModifier(e), Mouse.IsRightMouseButtonPressed(e), e.type == EventType.MouseDown); if (ProcessMouseDownIfNeeded( e, itemsGridView, doubleClickAction, selectedItemsIndexes, itemIndexToSelect, shouldUpdateSelection)) return true; if (ProcessMouseUpIfNeeded( e, menu, itemsGridView, selectedItemsIndexes, itemIndexToSelect, shouldUpdateSelection)) return true; return false; } static bool ProcessMouseDownIfNeeded( Event e, IItemsGridView itemsGridView, Action doubleClickAction, List selectedItemsIndexes, int itemIndexToSelect, bool shouldUpdateSelection) { if (e.type != EventType.MouseDown) return false; if (Mouse.IsLeftMouseButtonDoubleClicked(e)) { if (itemIndexToSelect == -1) return false; doubleClickAction(); return true; } if (!shouldUpdateSelection) return true; HandleMouseSelection( itemsGridView, selectedItemsIndexes, itemIndexToSelect, Keyboard.HasControlOrCommandModifier(e), Keyboard.HasShiftModifier(e)); return true; } static bool ProcessMouseUpIfNeeded( Event e, DirectoryContentPanelMenu menu, IItemsGridView itemsGridView, List selectedItemsIndexes, int itemIndexToSelect, bool shouldUpdateSelection) { if (e.type != EventType.MouseUp) return false; if (Mouse.IsLeftMouseButtonDoubleClicked(e)) return false; if (Mouse.IsRightMouseButtonPressed(e)) { menu.Popup(); return true; } if (!shouldUpdateSelection) return true; HandleMouseSelection( itemsGridView, selectedItemsIndexes, itemIndexToSelect, Keyboard.HasControlOrCommandModifier(e), Keyboard.HasShiftModifier(e)); return true; } static bool ProcessKeyDownIfNeeded( Event e, DirectoryContentPanelMenu menu, IItemsGridView itemsGridView, Action navigateBackAction, List selectedItemsIndexes, int columnsCount, int itemsCount) { if (e.type != EventType.KeyDown) return false; if (menu.ProcessKeyActionIfNeeded(e)) return true; bool shouldExtendSelection = Keyboard.HasControlOrCommandModifier(e) || Keyboard.HasShiftModifier(e); switch (e.keyCode) { case KeyCode.Backspace: navigateBackAction(); break; case KeyCode.UpArrow: HandleKeyboardSelection( itemsGridView, selectedItemsIndexes, GetItemIndexToSelectForOffset(selectedItemsIndexes, -columnsCount), itemsCount, shouldExtendSelection); break; case KeyCode.DownArrow: HandleKeyboardSelection( itemsGridView, selectedItemsIndexes, GetItemIndexToSelectForOffset(selectedItemsIndexes, columnsCount), itemsCount, shouldExtendSelection); break; case KeyCode.LeftArrow: HandleKeyboardSelection( itemsGridView, selectedItemsIndexes, GetItemIndexToSelectForOffset(selectedItemsIndexes, -1), itemsCount, shouldExtendSelection); break; case KeyCode.RightArrow: HandleKeyboardSelection( itemsGridView, selectedItemsIndexes, GetItemIndexToSelectForOffset(selectedItemsIndexes, 1), itemsCount, shouldExtendSelection); break; } return true; } static bool ProcessMouseDragIfNeeded( Event e, IItemsGridView itemsGridView, IDragAndDrop dragAndDrop, EditorWindow parentWindow, Rect rect, Vector2 itemSize, float scrollPosition, int columnsCount, int itemsCount, bool isScrollbarVisible, bool isDragAvailable) { if (!isDragAvailable) return false; if (e.type == EventType.MouseDrag) { ProcessDragEvent.ProcessMouseDrag(dragAndDrop, parentWindow); return true; } if (e.type == EventType.DragExited) { ProcessDragEvent.ProcessDragExited(itemsGridView, dragAndDrop); return true; } if (e.type == EventType.DragUpdated) { ProcessDragEvent.ProcessDragUpdated( itemsGridView, dragAndDrop, parentWindow, e.mousePosition, rect, itemSize, scrollPosition, columnsCount, itemsCount, isScrollbarVisible); return true; } if (e.type == EventType.DragPerform) { ProcessDragEvent.ProcessDragPerform( itemsGridView, dragAndDrop, parentWindow, e.mousePosition, rect, itemSize, scrollPosition, columnsCount, itemsCount, isScrollbarVisible); return true; } return false; } static void HandleMouseSelection( IItemsGridView itemsGridView, List selectedItemsIndexes, int itemIndexToSelect, bool shouldToggleSelection, bool shouldExtendSelection) { if (itemIndexToSelect == -1) { itemsGridView.ClearSelectedItems(); return; } List indexesToSelect = GetItemsIndexesToSelect( selectedItemsIndexes, itemIndexToSelect, shouldToggleSelection, shouldExtendSelection); if (indexesToSelect.Count == 0) { itemsGridView.ClearSelectedItems(); return; } itemsGridView.SetSelection(indexesToSelect); } static void HandleKeyboardSelection( IItemsGridView itemsGridView, List selectedItemsIndexes, int itemIndexToSelect, int itemsCount, bool shouldExtendSelection) { if (itemIndexToSelect < 0 || itemIndexToSelect >= itemsCount) return; List indexesToSelect = GetItemsIndexesToSelect( selectedItemsIndexes, itemIndexToSelect, false, shouldExtendSelection); if (indexesToSelect.Count == 0) { itemsGridView.ClearSelectedItems(); return; } itemsGridView.SetSelection(indexesToSelect); } static bool ShouldUpdateSelection( bool clickedOnSelection, bool hasControlPressed, bool isRightClick, bool isMouseDown) { if (isRightClick) return !clickedOnSelection && !hasControlPressed && isMouseDown; if (clickedOnSelection && !hasControlPressed) return !isMouseDown; return isMouseDown; } static int GetItemIndexToSelectForOffset( List selectedItemsIndexes, int offset) { if (selectedItemsIndexes.Count == 0) return 0; return selectedItemsIndexes.Last() + offset; } static List GetItemsIndexesToSelect( List selectedItemsIndexes, int indexToSelect, bool shouldToggleSelection, bool shouldExtendSelection) { if (shouldExtendSelection) { return GetItemsIndexesToSelectByExtending( selectedItemsIndexes, indexToSelect); } if (shouldToggleSelection) { return GetItemsIndexesToSelectByToggling( selectedItemsIndexes, indexToSelect); } return new List { indexToSelect }; } static List GetItemsIndexesToSelectByExtending( IList selectedItemsIndexes, int target) { int anchor = selectedItemsIndexes.FirstOrDefault(); int direction = anchor < target ? 1 : -1; int count = Math.Abs(target - anchor); List result = new List(); for (int i = 0; i <= count; i++) result.Add(anchor + i * direction); return result; } static List GetItemsIndexesToSelectByToggling( IList selectedItemsIndexes, int target) { List result = new List(selectedItemsIndexes); if (result.Contains(target)) { result.Remove(target); return result; } result.Add(target); return result; } } }