// // Copyright 2014 Perforce Software Inc. // using Perforce.Helper; using Perforce.Model; using Perforce.P4; using Perforce.ViewModel; using System; using System.Collections.Generic; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using Technewlogic.WpfDialogManagement; namespace Perforce.View { /// /// Interaction logic for ColumnDisplay.xaml /// public partial class ColumnDisplay : UserControl, Refreshable { private ColumnDisplayViewModel _model; private SidebarSelector _selector; public ColumnDisplay(SidebarSelector selector, int column = 0, string path = null, string header = null, string selected = null, bool loadSynchronous = false) { InitializeComponent(); if (!string.IsNullOrEmpty(header)) { Header.Visibility = Visibility.Visible; HeaderName.Content = header; } _selector = selector; Listing.Background = this.Background; Listing.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged; _model = new ColumnDisplayViewModel(selector, this, column, path, selected, loadSynchronous); this.DataContext = _model; if (selector.Model != null) { selector.Model.CurrentColumn = this; } } void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) { if (Listing.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) { int index = Listing.SelectedIndex; if (index >= 0) { ListViewItem item = Listing.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem; if (item != null) { item.Focus(); } } } } public SidebarSelector Selector { get { return _selector; } } public ColumnDisplayViewModel Model { get { return _model; } } public void Refresh(bool sync = false) { _model.Refresh(sync); Listing.UpdateLayout(); UIHelper.ScrollToRight(); } private void ColumnDisplay_Loaded(object sender, RoutedEventArgs e) { var selectedItem = _model.SelectedItem; if (selectedItem != null) { Listing.SelectedItem = selectedItem; } UIHelper.ScrollToRight(); //foreach (var i in Listing.Items) { // (i as ListingItem).Refresh(); //} } //private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // UpdateSelection(); //} public void UpdateSelection() { MainWindow main = App.Current.MainWindow as MainWindow; // first clear the selected flags foreach (var item in Listing.Items) { (item as ListingItem).IsSelected = false; } if (Listing.SelectedItems.Count == 1) { var item = Listing.SelectedItem as ListingItem; item.IsSelected = true; main.HandleListingItemClick(item as ListingItem); } else if (Listing.SelectedItems.Count > 1) { foreach (var item in Listing.SelectedItems) { (item as ListingItem).IsSelected = true; } } ListingItem[] array = new ListingItem[Listing.SelectedItems.Count]; Listing.SelectedItems.CopyTo(array, 0); _selector.Model.CurrentSelection = array; main.RefreshBreadcrumbs(); } private void Listing_MouseUp(object sender, MouseButtonEventArgs e) { UpdateSelection(); } private void Listing_Drop(object sender, DragEventArgs e) { FrameworkElement element = (FrameworkElement) sender; var lvi = (ListViewItem) Listing.ItemContainerGenerator.ContainerFromItem(element.DataContext); if (lvi != null) { var item = lvi.DataContext as ListingItem; if (e.Data.GetDataPresent(DataFormats.FileDrop)) { // Note that you can have more than one file. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); CommandHelper.MoveLocalFiles(files, item.ClientPath); } e.Handled = true; (sender as Border).Background = Brushes.Transparent; } } private void Column_Drop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { // Note that you can have more than one file. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); CommandHelper.MoveLocalFiles(files, Model.Path); } e.Handled = true; } private void Border_KeyUp(object sender, KeyEventArgs e) { var grid = _selector.SidbebarView.ListingGrid; switch (e.Key) { case System.Windows.Input.Key.Up: case System.Windows.Input.Key.Down: UpdateSelection(); e.Handled = true; break; case System.Windows.Input.Key.Return: case System.Windows.Input.Key.Right: var nextCol = GridHelper.GetGridColumn(grid, Model.ColumnNumber + 1); if (nextCol != null) { nextCol.ScrollArea.ScrollToTop(); nextCol.Listing.SelectedIndex = 0; var lvi = nextCol.Listing.ItemContainerGenerator.ContainerFromIndex(0) as ListViewItem; if (lvi != null) lvi.Focus(); if (nextCol.Listing.Items.Count > 0) { var itm = nextCol.Listing.Items[0] as ListingItem; if (itm != null) itm.IsSelected = true; nextCol.UpdateSelection(); } } e.Handled = true; break; case System.Windows.Input.Key.Left: if (Model.ColumnNumber > 0) { var prevCol = GridHelper.GetGridColumn(grid, Model.ColumnNumber - 1); var lvi = prevCol.Listing.ItemContainerGenerator.ContainerFromIndex(prevCol.Listing.SelectedIndex) as ListViewItem; if(lvi != null) lvi.Focus(); e.Handled = true; } break; } } private void Border_DragEnter(object sender, DragEventArgs e) { (sender as Border).Background = Brushes.LightBlue; } private void Border_DragLeave(object sender, DragEventArgs e) { (sender as Border).Background = Brushes.Transparent; } private void Border_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { FrameworkElement element = (FrameworkElement)sender; var lvi = (ListViewItem)Listing.ItemContainerGenerator.ContainerFromItem(element.DataContext); if (lvi != null) { var li = lvi.Content as ListingItem; li.RefreshContextMenu(); } } // handle a double-click on a file private void File_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (e.ClickCount == 2) { FrameworkElement element = (FrameworkElement)sender; var lvi = (ListViewItem)Listing.ItemContainerGenerator.ContainerFromItem(element.DataContext); if (lvi != null && lvi.Content is FileItem) { var item = lvi.Content as FileItem; if (item.IsMapped) { if (!MetadataHelper.CanEdit(item)) { UIHelper.ShowMessage(string.Format("{0} is locked ... cannot open", item.LabelText)); } else { CommandHelper.CheckoutAndOpenFile(item); //CommandHelper.CheckoutFiles(item); //CommandHelper.OpenLocalFile(item.ClientPath, makeWritable: true); } } } } } private string COPY_DATA_FORMAT = "CopyListingItems"; private void Copy_CanExecute(object sender, CanExecuteRoutedEventArgs e) { var canCopy = false; if (_selector.SelectorType == SELECTOR_TYPE.WORKSPACE || _selector.SelectorType == SELECTOR_TYPE.SERVER) { canCopy = true; } e.CanExecute = canCopy; } private void Copy_Executed(object sender, ExecutedRoutedEventArgs e) { var list = e.Source as ListView; if (list.SelectedItems != null && list.SelectedItems.Count > 0) { var helper = Utility.GetPerforceHelper(); var copiedItems = new List(); foreach (var i in list.SelectedItems) { var li = i as ListingItem; if (li is FolderItem) { // if we're copying a folder that's in Perforce, let's ensure that // the user knows what s/he is doing if (!li.DepotPath.StartsWith(Constants.DUMMY_DEPOT_PATH)) { var main = App.Current.MainWindow as MainWindow; var size = helper.GetPathSizes(li.DepotPath); var msg = string.Format("Are you sure you want to copy this folder:\n Folder Name: {0}\n Number of Files: {1}\n Folder size: {2} KB", li.LabelText, size.FileCount, size.FileSize / 1024); var dialog = main.DialogManager.CreateMessageDialog(msg, DialogMode.OkCancel); dialog.VerticalDialogAlignment = System.Windows.VerticalAlignment.Top; dialog.OkText = "Copy"; dialog.CancelText = "Skip"; dialog.Ok = () => { CopyToClipboard(li); }; dialog.Show(); } else { CopyToClipboard(li); } } else { CopyToClipboard(li); } } if (Clipboard.ContainsData(COPY_DATA_FORMAT)) { var items = Clipboard.GetData(COPY_DATA_FORMAT) as List; UIHelper.ShowTimedMessage("item(s) copied to clipboard", .5); } } e.Handled = true; } private void CopyToClipboard(ListingItem item) { List copiedItems = null; if (Clipboard.ContainsData(COPY_DATA_FORMAT)) { copiedItems = Clipboard.GetData(COPY_DATA_FORMAT) as List; } else { copiedItems = new List(); } var copyItem = new CopyPasteItem { FileName = item.LabelText, ClientPath = item.ClientPath, DepotPath = item.DepotPath, IsFolder = (item is FolderItem), IsMapped = item.IsMapped }; copiedItems.Add(copyItem); DataObject data = new DataObject(); data.SetData(COPY_DATA_FORMAT, copiedItems); Clipboard.SetDataObject(data); } private string CUT_DATA_FORMAT = "CutListingItems"; private void Cut_CanExecute(object sender, CanExecuteRoutedEventArgs e) { var canCut = false; e.CanExecute = canCut; } private void Paste_CanExecute(object sender, CanExecuteRoutedEventArgs e) { var canPaste = false; if ((_selector.SelectorType == SELECTOR_TYPE.WORKSPACE) && (Clipboard.ContainsData(COPY_DATA_FORMAT) || Clipboard.ContainsData(CUT_DATA_FORMAT))) { canPaste = true; } e.CanExecute = canPaste; } private void Paste_Executed(object sender, ExecutedRoutedEventArgs e) { var listView = sender as ListView; if (listView != null) { if (listView.SelectedItems.Count != 1) { UIHelper.ShowMessage("You must select a single folder to paste"); return; } var item = listView.SelectedItem as ListingItem; if (item.ClientPath == null) { UIHelper.ShowMessage("Error selecting destination path"); return; } var targetDirParent = item.ClientPath; if (item is FileItem) { var fi = new FileInfo(item.ClientPath); targetDirParent = fi.DirectoryName; } if (Clipboard.ContainsData(COPY_DATA_FORMAT)) { var items = Clipboard.GetData(COPY_DATA_FORMAT) as List; var main = App.Current.MainWindow as MainWindow; var dialog = main.DialogManager.CreateWaitDialog("copying files... please wait", DialogMode.Ok); dialog.VerticalDialogAlignment = System.Windows.VerticalAlignment.Top; dialog.CanOk = false; dialog.Show(() => { // PERFORM A COPY WITHIN A WAIT DIALOG var helper = Utility.GetPerforceHelper(); Utility.StopBackgroundProcesses(); foreach (var i in items) { if (!i.IsFolder) { var targetFile = string.Empty; if (i.IsMapped || i.DepotPath.StartsWith(Constants.DUMMY_DEPOT_PATH)) { // copy file locally on the filesystem targetFile = Utility.CopyFileToDirectory(i.ClientPath, targetDirParent); } else { // first download the file var tmpfile = helper.GetFileFromServer(i.DepotPath); targetFile = Utility.CopyFileToDirectory(tmpfile, targetDirParent, i.FileName); } if (!string.IsNullOrEmpty(targetFile)) { helper.MarkFileForAdd(targetFile); } } else { var targetDir = Path.Combine(targetDirParent, i.FileName); if (i.IsMapped || i.DepotPath.StartsWith(Constants.DUMMY_DEPOT_PATH)) { Utility.CopyDirectory(i.ClientPath, targetDir); } else { helper.GetDirectoryFromServer(i.DepotPath, targetDirParent); } helper.ReconcileFiles(targetDirParent + "\\..."); } } dialog.CanOk = true; Utility.StartBackgroundProcesses(); }); Clipboard.Clear(); } else if (Clipboard.ContainsData(CUT_DATA_FORMAT)) { var obj = Clipboard.GetData(CUT_DATA_FORMAT); Log.Debug(string.Format("-- {0}", obj.GetType().ToString())); } } } public static RoutedCommand RevertCommand = new RoutedCommand(); private void RevertCommand_Executed( object sender, ExecutedRoutedEventArgs e ) { var itemsToRevert = new List(); var col = e.Source as ColumnDisplay; if (col != null) { if (col.Listing != null && col.Listing.SelectedItems != null && col.Listing.SelectedItems.Count > 0) { foreach (var i in col.Listing.SelectedItems) { var li = i as FileItem; if (li != null) { itemsToRevert.Add(li); } } } } if (itemsToRevert.Count > 0) { CommandHelper.RevertFiles(itemsToRevert.ToArray()); } } private void RevertCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; } public static RoutedCommand SubmitCommand = new RoutedCommand(); private void SubmitCommand_Executed(object sender, ExecutedRoutedEventArgs e) { var helper = Utility.GetPerforceHelper(); var itemsToSubmit = new List(); var col = e.Source as ColumnDisplay; if (col != null) { if (col.Listing != null && col.Listing.SelectedItems != null && col.Listing.SelectedItems.Count > 0) { foreach (var i in col.Listing.SelectedItems) { if (i is FolderItem) { } else if (i is FileItem) { var li = i as FileItem; if (li != null) { itemsToSubmit.Add(li.DepotPath); var md = helper.RunFstat(li.DepotPath); if (md != null) { if (md.Action == FileAction.MoveAdd) { if (!itemsToSubmit.Contains(md.MovedFile.Path)) { itemsToSubmit.Add(md.MovedFile.Path); } } else if (md.Action == FileAction.MoveDelete) { if (!itemsToSubmit.Contains(md.MovedFile.Path)) { itemsToSubmit.Add(md.MovedFile.Path); } } } } } } } } if (itemsToSubmit.Count > 0) { CommandHelper.SubmitChangelist(selected: itemsToSubmit.ToArray()); } } private void SubmitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; } } [Serializable] public class CopyPasteItem { public string FileName { get; set; } public string ClientPath { get; set; } public string DepotPath { get; set; } public bool IsFolder { get; set; } public bool IsMapped { get; set; } } }