// // Copyright 2014 Perforce Software Inc. // using Perforce.ViewModel; using Perforce.Model; using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; using Perforce.P4; using System.Collections; using System.Linq; using System.Collections.Generic; namespace Perforce.Helper { public class ContextMenuHelper { public static ObservableCollection GetContextMenu(ListingItem item) { Log.TraceFunction(); var items = item.ColumnContext.Listing.SelectedItems; var contextMenu = new ObservableCollection(); if (items.Count > 1) { contextMenu.Add(new MenuItem { Header = "", IsEnabled = false }); } else if (items.Count == 1) { contextMenu.Add(new MenuItem { Header = (items[0] as ListingItem).LabelText, IsEnabled = false, FontWeight = FontWeights.Bold }); } else { return null; } contextMenu.Add(new Separator()); switch (item.ColumnContext.Selector.SelectorType) { case SELECTOR_TYPE.WORKSPACE: ConfigureWorkspaceContextMenu(contextMenu, items); break; case SELECTOR_TYPE.SERVER: case SELECTOR_TYPE.SEARCH: ConfigureServerContextMenu(contextMenu, items); break; case SELECTOR_TYPE.PENDING: ConfigurePendingContextMenu(contextMenu, items); break; case SELECTOR_TYPE.RECENT: ConfigureRecentContextMenu(contextMenu, items); break; case SELECTOR_TYPE.TRASH: ConfigureTrashContextMenu(contextMenu, items); break; case SELECTOR_TYPE.FAVORITE: var fav = (item.ColumnContext.Selector.Model as FavoritesViewModel).Item; if (fav.Selector == SELECTOR_TYPE.WORKSPACE) { ConfigureWorkspaceContextMenu(contextMenu, items); } else { ConfigureServerContextMenu(contextMenu, items); } break; } return contextMenu; } private static void ConfigureTrashContextMenu(ObservableCollection contextMenu, IList items) { Log.TraceFunction(); if (items.Count == 1) { var item = items[0] as ListingItem; if (item.Type.Equals(ListingItem.TYPE.FILE)) { var file = item as FileItem; if (MetadataHelper.CanRevert(file)) { contextMenu.Add(new MenuItem { Header = "Undo trash", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = file }); } contextMenu.Add(new MenuItem { Header = "Submit file", IsEnabled = true, Command = new DelegateCommand(SubmitFiles), CommandParameter = file }); } } else { contextMenu.Add(new MenuItem { Header = "Undo trash (all selected)", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = items }); contextMenu.Add(new MenuItem { Header = "Submit selected files", InputGestureText="Ctrl+S", IsEnabled = true, Command = new DelegateCommand(SubmitFiles), CommandParameter = items }); } } private static void ConfigureRecentContextMenu(ObservableCollection contextMenu, IList items) { Log.TraceFunction(); if (items.Count == 1) { var item = items[0] as ListingItem; if (item.Type.Equals(ListingItem.TYPE.FILE)) { var file = item as FileItem; var editable = MetadataHelper.CanEdit(file); var revertable = MetadataHelper.CanRevert(file); contextMenu.Add(new MenuItem { Header = "Open", IsEnabled = editable, Command = new DelegateCommand(OpenWorkspaceFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Open readonly", IsEnabled = true, Command = new DelegateCommand(ViewWorkspaceFile), CommandParameter = file }); if (editable) { contextMenu.Add(new MenuItem { Header = "Edit file", IsEnabled = true, Command = new DelegateCommand(CheckoutFile), CommandParameter = file }); } if (revertable) { contextMenu.Add(new MenuItem { Header = "Revert changes", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = file }); } contextMenu.Add(new MenuItem { Header = "Mark as read", IsEnabled = true, Command = new DelegateCommand(MarkRead), CommandParameter = file }); } else { // should never see folders in the recent list } contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = true, Command = new DelegateCommand(ShowInExplorer), CommandParameter = item }); } else { contextMenu.Add(new MenuItem { Header = "Revert selected files", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = items }); contextMenu.Add(new MenuItem { Header = "Mark selected read", IsEnabled = true, Command = new DelegateCommand(MarkRead), CommandParameter = items }); } } private static void ConfigurePendingContextMenu(ObservableCollection contextMenu, IList items) { Log.TraceFunction(); if (items.Count == 1) { var item = items[0] as ListingItem; if (item.Type.Equals(ListingItem.TYPE.FILE)) { var file = item as FileItem; var editable = MetadataHelper.CanEdit(file); var revertable = MetadataHelper.CanRevert(file); contextMenu.Add(new MenuItem { Header = "Open", IsEnabled = editable, Command = new DelegateCommand(OpenWorkspaceFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Open readonly", IsEnabled = true, Command = new DelegateCommand(ViewWorkspaceFile), CommandParameter = file }); if (editable) { contextMenu.Add(new MenuItem { Header = "Edit file", IsEnabled = true, Command = new DelegateCommand(CheckoutFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Trash", IsEnabled = editable, Command = new DelegateCommand(DeleteFile), CommandParameter = file }); } if (revertable) { contextMenu.Add(new MenuItem { Header = "Revert changes", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = file }); } contextMenu.Add(new MenuItem { Header = "Submit file", InputGestureText="Ctrl+S", IsEnabled = true, Command = new DelegateCommand(SubmitFiles), CommandParameter = file }); } else { // should never see folders in the pending list } contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = true, Command = new DelegateCommand(ShowInExplorer), CommandParameter = item }); } else { contextMenu.Add(new MenuItem { Header = "Revert selected files", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = items }); contextMenu.Add(new MenuItem { Header = "Submit selected files", InputGestureText="Ctrl+S", IsEnabled = true, Command = new DelegateCommand(SubmitFiles), CommandParameter = items }); } } private static void ConfigureServerContextMenu(ObservableCollection contextMenu, IList items) { Log.TraceFunction(); if (items.Count == 1) { var item = items[0] as ListingItem; var p4 = Utility.GetPerforceHelper(); if (item.Type.Equals(ListingItem.TYPE.FILE)) { var file = item as FileItem; var editable = MetadataHelper.CanEdit(file); contextMenu.Add(new MenuItem { Header = "Open", IsEnabled = editable, Command = new DelegateCommand(OpenWorkspaceFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Open readonly", IsEnabled = editable, Command = new DelegateCommand(ViewWorkspaceFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Open file from server", IsEnabled = true, Command = new DelegateCommand(OpenFromServer), CommandParameter = file }); contextMenu.Add(new Separator()); contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = item.IsMapped, Command = new DelegateCommand(ShowInExplorer), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Show Versions", IsEnabled = true, Command = new DelegateCommand(ShowVersions), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Copy link", IsEnabled = true, Command = new DelegateCommand(CopyLink), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Trash", IsEnabled = editable, Command = new DelegateCommand(DeleteFile), CommandParameter = file }); } else { var folder = item as FolderItem; if (p4.ClientFolderMappingContains(item.DepotPath)) { contextMenu.Add(new MenuItem { Header = "Unsync from computer", IsEnabled = true, Command = new DelegateCommand(UnsyncFromComputer), CommandParameter = folder }); } else if (!folder.IsMapped) { contextMenu.Add(new MenuItem { Header = "Sync with computer", IsEnabled = true, Command = new DelegateCommand(SyncWithComputer), CommandParameter = folder }); } contextMenu.Add(new MenuItem { Header = "Add to Favorites", IsEnabled = true, Command = new DelegateCommand(AddToFavorites), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = folder.IsMapped, Command = new DelegateCommand(ShowInExplorer), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Show Folder History", IsEnabled = folder.IsMapped, Command = new DelegateCommand(ShowFolderHistory), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Copy link", IsEnabled = true, Command = new DelegateCommand(CopyLink), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Trash", IsEnabled = folder.IsMapped, Command = new DelegateCommand(DeleteFile), CommandParameter = folder }); } } else { // multiple selection } } private static void ConfigureWorkspaceContextMenu(ObservableCollection contextMenu, IList items) { Log.TraceFunction(); if (items.Count == 1) { var item = items[0] as ListingItem; if (item.Type.Equals(ListingItem.TYPE.FILE)) { var file = item as FileItem; var editable = MetadataHelper.CanEdit(file); var revertable = MetadataHelper.CanRevert(file); contextMenu.Add(new MenuItem { Header = "Open", IsEnabled = editable, Command = new DelegateCommand(OpenWorkspaceFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Open readonly", IsEnabled = true, Command = new DelegateCommand(ViewWorkspaceFile), CommandParameter = file }); if (editable) { contextMenu.Add(new MenuItem { Header = "Edit file", IsEnabled = true, Command = new DelegateCommand(CheckoutFile), CommandParameter = file }); } if (revertable) { contextMenu.Add(new MenuItem { Header = "Revert changes", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Submit file", InputGestureText="Ctrl+S", IsEnabled = true, Command = new DelegateCommand(SubmitFiles), CommandParameter = file }); } contextMenu.Add(new MenuItem { Header = "Show Versions", IsEnabled = item.IsMapped, Command = new DelegateCommand(ShowVersions), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = true, Command = new DelegateCommand(ShowInExplorer), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Copy link", IsEnabled = item.IsMapped, Command = new DelegateCommand(CopyLink), CommandParameter = file }); contextMenu.Add(new MenuItem { Header = "Trash", IsEnabled = editable, Command = new DelegateCommand(DeleteFile), CommandParameter = file }); } else { var folder = item as FolderItem; contextMenu.Add(new MenuItem { Header = "Edit all files", IsEnabled = folder.IsMapped, Command = new DelegateCommand(CheckoutFile), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Revert all files", InputGestureText="Ctrl+R", IsEnabled = folder.IsMapped, Command = new DelegateCommand(RevertFile), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Submit all files", InputGestureText="Ctrl+S", IsEnabled = folder.IsMapped, Command = new DelegateCommand(SubmitFolder), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Add to Favorites", IsEnabled = true, Command = new DelegateCommand(AddToFavorites), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Show in Explorer", IsEnabled = folder.IsMapped, Command = new DelegateCommand(ShowInExplorer), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Reconcile Files", IsEnabled = folder.IsMapped, Command = new DelegateCommand(ReconcileFiles), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Show Folder History", IsEnabled = folder.IsMapped, Command = new DelegateCommand(ShowFolderHistory), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Copy link", IsEnabled = true, Command = new DelegateCommand(CopyLink), CommandParameter = folder }); contextMenu.Add(new MenuItem { Header = "Trash", IsEnabled = folder.IsMapped, Command = new DelegateCommand(DeleteFile), CommandParameter = folder }); } } else if (items.Count > 1) { // multiple selections if (AllFiles(items)) { contextMenu.Add(new MenuItem { Header = "Edit selected files", IsEnabled = true, Command = new DelegateCommand(CheckoutFile), CommandParameter = items }); contextMenu.Add(new MenuItem { Header = "Revert selected files", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = items }); } else { contextMenu.Add(new MenuItem { Header = "Edit selected files", IsEnabled = true, Command = new DelegateCommand(CheckoutFile), CommandParameter = items }); contextMenu.Add(new MenuItem { Header = "Revert selected files", InputGestureText="Ctrl+R", IsEnabled = true, Command = new DelegateCommand(RevertFile), CommandParameter = items }); } } } private static bool AllFiles(IList items) { var allFiles = false; foreach (var item in items) { if((item as ListingItem).Type.Equals(ListingItem.TYPE.FOLDER)) { break; } allFiles = true; } return allFiles; } #region COMMANDS private static void SyncWithComputer(object parameter) { Log.TraceFunction(); ListingItem[] items = null; if (parameter is ListingItem) { items = new ListingItem[1]; items[0] = parameter as ListingItem; } else if (parameter is IList) { var list = parameter as IList; items = list.Cast().ToArray(); } if(items != null && items.Length > 0) { UIHelper.SetBusyState(); Utility.StopBackgroundProcesses(); var helper = Utility.GetPerforceHelper(); var main = App.Current.MainWindow as MainWindow; var waitDialog = main.DialogManager.CreateWaitDialog("Synchronizing files", string.Empty, Technewlogic.WpfDialogManagement.DialogMode.Ok); waitDialog.VerticalDialogAlignment = VerticalAlignment.Top; waitDialog.Show(() => { foreach (var item in items) { var path = item.DepotPath; if (item is FolderItem) { path += "/..."; } helper.ClientFolderMappingAdd(path); var result = helper.RunSync(path); if (result != null && result.Count > 0) { waitDialog.ReadyMessage = string.Format("{0} files synchronized from server", result.Count); } else { waitDialog.ReadyMessage = "No files synchronized from server"; } item.Refresh(); } Utility.StartBackgroundProcesses(); UIHelper.RefreshSelectorAsync(SELECTOR_TYPE.WORKSPACE); }); } } private static void UnsyncFromComputer(object parameter) { Log.TraceFunction(); ListingItem[] items = null; if (parameter is ListingItem) { items = new ListingItem[1]; items[0] = parameter as ListingItem; } else if (parameter is IList) { var list = parameter as IList; items = list.Cast().ToArray(); } if (items != null && items.Length > 0) { UIHelper.SetBusyState(); var helper = Utility.GetPerforceHelper(); var main = App.Current.MainWindow as MainWindow; foreach (var item in main.CurrentSelection) { var path = item.DepotPath; if (item is FolderItem) { path += "/..."; } helper.RunSync(path, "#0"); helper.ClientFolderMappingRemove(path); item.Refresh(); } UIHelper.RefreshSelectorAsync(SELECTOR_TYPE.WORKSPACE); } } private static void OpenWorkspaceFile(object parameter) { Log.TraceFunction(); if (parameter is FileItem) { var item = parameter as FileItem; CommandHelper.CheckoutAndOpenFile(item); item.Refresh(); UIHelper.RefreshCurrent(); UIHelper.RefreshSelector(SELECTOR_TYPE.PENDING); } } private static void ViewWorkspaceFile(object parameter) { Log.TraceFunction(); if (parameter is FileItem) { var item = parameter as FileItem; CommandHelper.OpenLocalFile(item.ClientPath); } } private static void OpenFromServer(object parameter) { Log.TraceFunction(); if (parameter is FileItem) { var item = parameter as FileItem; CommandHelper.OpenFileFromServer(item.DepotPath); } } private static void AddToFavorites(object parameter) { Log.TraceFunction(); if (parameter is FolderItem) { var item = parameter as FolderItem; CommandHelper.AddToFavorites(item); } } private static void ShowInExplorer(object parameter) { Log.TraceFunction(); if (parameter is ListingItem) { var item = parameter as ListingItem; CommandHelper.ShowFileInExplorer(item.ClientPath); } } private static void CheckoutFile(object parameter) { Log.TraceFunction(); var helper = Utility.GetPerforceHelper(); if (parameter is ListingItem) { if (parameter is FolderItem) { var folder = parameter as FolderItem; if (helper.PathHasAnyOpened(folder.ClientPath + "/...")) { UIHelper.ShowMessage(string.Format("Sorry, {0} has locked files", folder.ClientPath)); return; } } var item = parameter as ListingItem; CommandHelper.CheckoutFiles(items: item); item.Refresh(); } else if (parameter is IList) { var list = parameter as IList; var items = list.Cast().ToArray(); CommandHelper.CheckoutFiles(items: items); foreach (var item in items) { item.Refresh(); } } UIHelper.RefreshSelector(SELECTOR_TYPE.PENDING); } private static void DeleteFile(object parameter) { Log.TraceFunction(); if (parameter is ListingItem) { var item = parameter as ListingItem; CommandHelper.DeleteFiles(item); item.Refresh(); } else if (parameter is IList) { var list = parameter as IList; var items = list.Cast().ToArray(); CommandHelper.DeleteFiles(items); foreach (var item in items) { item.Refresh(); } } UIHelper.RefreshCurrent(); } private static void RevertFile(object parameter) { Log.TraceFunction(); if (parameter is ListingItem) { var item = parameter as ListingItem; CommandHelper.RevertFiles(item); item.Refresh(); } else if (parameter is IList) { var list = parameter as IList; var items = list.Cast().ToArray(); CommandHelper.RevertFiles(items); foreach (var item in items) { item.Refresh(); } } } private static void MarkRead(object parameter) { Log.TraceFunction(); var main = App.Current.MainWindow as MainWindow; var set = Utility.GetRecentSet(); if (parameter is ListingItem) { var item = parameter as ListingItem; CommandHelper.RevertFiles(item); item.Refresh(); set.Remove(item); } else if (parameter is IList) { var list = parameter as IList; var items = list.Cast().ToArray(); CommandHelper.RevertFiles(items); foreach (var item in items) { item.Refresh(); set.Remove(item); } } UIHelper.RefreshSelector(SELECTOR_TYPE.RECENT); } private static void ReconcileFiles(object parameter) { Log.TraceFunction(); ListingItem[] items = null; if (parameter is ListingItem) { items = new ListingItem[1]; items[0] = parameter as ListingItem; } else if (parameter is IList) { var list = parameter as IList; items = list.Cast().ToArray(); } var main = App.Current.MainWindow as MainWindow; var waitDialog = main.DialogManager.CreateWaitDialog("Reconciling files (this may take a while)", string.Empty, Technewlogic.WpfDialogManagement.DialogMode.Ok); waitDialog.VerticalDialogAlignment = VerticalAlignment.Top; waitDialog.Show(() => { var result = CommandHelper.ReconcileFiles(items); if (result != null && result.Success) { waitDialog.ReadyMessage = "Reconcile complete"; } else { waitDialog.ReadyMessage = "Reconcile failed"; } }); main.RefreshCurrent(); } private static void SubmitFolder(object parameter) { Log.TraceFunction(); if (parameter is FolderItem) { var folder = parameter as FolderItem; CommandHelper.SubmitFolder(folder); } } private static void SubmitFiles(object parameter) { Log.TraceFunction(); var helper = Utility.GetPerforceHelper(); var items = new List(); if (parameter is ListingItem) { var itm = parameter as ListingItem; items.Add(itm.DepotPath); var md = helper.RunFstat(itm.DepotPath); if (md != null) { if (md.Action == FileAction.MoveAdd) { items.Add(md.MovedFile.Path); } else if (md.Action == FileAction.MoveDelete) { items.Add(md.MovedFile.Path); } } } else if (parameter is IList) { var list = parameter as IList; foreach (var i in list) { var itm = i as ListingItem; items.Add(itm.DepotPath); var md = helper.RunFstat(itm.DepotPath); if (md != null) { if (md.Action == FileAction.MoveAdd) { if (!items.Contains(md.MovedFile.Path)) { items.Add(md.MovedFile.Path); } } else if (md.Action == FileAction.MoveDelete) { if (!items.Contains(md.MovedFile.Path)) { items.Add(md.MovedFile.Path); } } } } } if (items.Count > 0) { CommandHelper.SubmitChangelist(selected: items.ToArray()); } } private static void ShowFolderHistory(object parameter) { Log.TraceFunction(); if (parameter is FolderItem) { var folder = parameter as FolderItem; var main = App.Current.MainWindow as MainWindow; main.DisplayCurrentFolderHistory(folder); } } private static void CopyLink(object parameter) { Log.TraceFunction(); if (parameter is ListingItem) { var item = parameter as ListingItem; if (item.DepotPath != null) { Clipboard.SetText(string.Format("p4:{0}", Utility.UrlEncodePath(item.DepotPath))); UIHelper.ShowTimedMessage("URL copied to clipboard", timeout: 0.5); } } } private static void ShowVersions(object parameter) { Log.TraceFunction(); if (parameter is FileItem) { var item = parameter as FileItem; var main = App.Current.MainWindow as MainWindow; main.DisplayCurrentItemVersionInfo(item); } } #endregion } }