//
// 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.Threading;
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);
Console.WriteLine("-- {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.GetFileMetaData(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; }
}
}