//
// Copyright 2014 Perforce Software Inc.
//
using Perforce.View;
using Perforce.ViewModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Text;
using Perforce.P4;
using Perforce.Model;
namespace Perforce.Helper {
public static class UIHelper {
#region BUSY_INDICATOR_LOGIC
///
/// A value indicating whether the UI is currently busy
///
private static bool IsBusy;
///
/// Sets the busystate as busy.
///
public static void SetBusyState() {
SetBusyState(true);
}
///
/// Sets the busystate to busy or not busy.
///
/// if set to true the application is now busy.
private static void SetBusyState(bool busy) {
if (busy != IsBusy) {
IsBusy = busy;
Mouse.OverrideCursor = busy ? Cursors.Wait : null;
if (IsBusy) {
new DispatcherTimer(TimeSpan.FromSeconds(0), DispatcherPriority.ApplicationIdle, dispatcherTimer_Tick, System.Windows.Application.Current.Dispatcher);
}
}
}
///
/// Handles the Tick event of the dispatcherTimer control.
///
/// The source of the event.
/// The instance containing the event data.
private static void dispatcherTimer_Tick(object sender, EventArgs e) {
var dispatcherTimer = sender as DispatcherTimer;
if (dispatcherTimer != null) {
SetBusyState(false);
dispatcherTimer.Stop();
}
}
#endregion
public static SidebarSelector GetCurrentSelector() {
var main = App.Current.MainWindow as MainWindow;
return main.Selectors.FindSelected();
}
public static SidebarSelector GetSelector(SELECTOR_TYPE type) {
var main = App.Current.MainWindow as MainWindow;
return main.Selectors.GetSelector(type);
}
public static void GoToPath(string originalPath, SELECTOR_TYPE type = SELECTOR_TYPE.NONE) {
if (originalPath.StartsWith("p4://")) originalPath = originalPath.Substring(3);
var path = Utility.DecodePath(originalPath);
var helper = Utility.GetPerforceHelper();
if (helper.PathExists(path)) {
var main = App.Current.MainWindow as MainWindow;
var selector = main.Selectors.GetSelector(SELECTOR_TYPE.SERVER);
GridHelper.GenerateGrid(selector, path);
main.Selectors.DeselectAll();
selector.Model.IsSelected = true;
main.ViewPane.Content = selector.SidbebarView;
main.Breadcrumbs.Model.UpdatePath();
} else {
ShowTimedMessage("Error: path does not exist", 1d);
}
}
public static void NavTo(NavItem location) {
var main = App.Current.MainWindow as MainWindow;
var selector = main.Selectors.GetSelector(location.Selector);
if (!string.IsNullOrEmpty(location.Path)) {
GridHelper.GenerateGrid(selector, location.Path);
}
main.Selectors.DeselectAll();
selector.Model.IsSelected = true;
main.ViewPane.Content = selector.SidbebarView;
main.Breadcrumbs.Model.UpdatePath();
main.Tools.Model.RefreshNavButtons();
}
public static void DisplayFavoriteFolder(FavoriteFolderItem fav) {
DeselectAllSelectors();
var visualSelector = GetSelector(fav.Selector);
visualSelector.Model.IsSelected = true;
visualSelector.Model.IsRefreshable = false;
var favoritesSelector = GetSelector(SELECTOR_TYPE.FAVORITE);
(favoritesSelector.Model as FavoritesViewModel).Item = fav;
favoritesSelector.Model.IsSelected = true;
GridHelper.InitializeGrid(favoritesSelector, path: fav.FolderPath, header: fav.FolderName);
var main = App.Current.MainWindow as MainWindow;
main.Tools.Model.RefreshAddButtons();
main.ViewPane.Content = favoritesSelector.SidbebarView;
}
public static void ClearSelectedFavorites() {
var favoritesSelector = GetSelector(SELECTOR_TYPE.FAVORITE);
GridHelper.ClearGrid(favoritesSelector.SidbebarView.ListingGrid);
favoritesSelector.Model.IsRefreshable = false;
favoritesSelector.Model.IsSelected = false;
}
public static void SetSyncInterval() {
var syncWorker = Utility.GetSyncBackgroundWorker();
var main = App.Current.MainWindow as MainWindow;
var form = new SyncIntervalDialog(syncWorker.Interval);
var dialog = main.DialogManager.CreateCustomContentDialog(form, Technewlogic.WpfDialogManagement.DialogMode.OkCancel);
dialog.OkText = "Set";
dialog.Ok = () => { OnSyncIntervalSet(form); };
dialog.VerticalDialogAlignment = VerticalAlignment.Top;
dialog.Show();
}
private static void OnSyncIntervalSet(SyncIntervalDialog form) {
var syncWorker = Utility.GetSyncBackgroundWorker();
int newInterval = -1;
bool success = int.TryParse(form.SyncIntervalText.Text, out newInterval);
if (success && newInterval > 0 && newInterval != syncWorker.Interval) {
syncWorker.Interval = newInterval;
}
}
public static void RefreshFavorites() {
var main = App.Current.MainWindow as MainWindow;
main.Selectors.Model.Refresh("FavoriteFolders");
}
public static void RefreshFavoriteTags() {
var main = App.Current.MainWindow as MainWindow;
main.Selectors.Model.Refresh("FavoriteTags");
}
public static void RefreshSelector(SELECTOR_TYPE type) {
var selector = GetSelector(type);
//if (selector != null && selector.Model != null) selector.Model.Refresh();
if (selector != null && selector.SidbebarView != null && selector.SidbebarView.ListingGrid != null) {
var grid = selector.SidbebarView.ListingGrid;
foreach (var child in grid.Children) {
if (child is Refreshable) {
(child as Refreshable).Refresh(sync: true);
}
}
if (selector.Model.IsSelected) {
for (var i = grid.Children.Count; i > 0; i--) {
var child = grid.Children[i-1];
if (child is ColumnDisplay) {
(child as ColumnDisplay).Focus();
break;
} else if (child is ListingItemInfo) {
(child as ListingItemInfo).Focus();
break;
}
}
UIHelper.ScrollToRight();
}
}
}
public static void RefreshSelectorAsync(SELECTOR_TYPE type) {
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => {
RefreshSelector(type);
}));
}
public static void RefreshCurrentColumn() {
var selector = GetCurrentSelector();
if (selector != null) {
if (selector.Model != null) {
if (selector.Model.CurrentColumn != null) {
selector.Model.CurrentColumn.Refresh();
}
}
}
}
public static void RefreshAllSelectors() {
RefreshSelector(SELECTOR_TYPE.WORKSPACE);
RefreshSelector(SELECTOR_TYPE.SERVER);
RefreshSelector(SELECTOR_TYPE.PENDING);
RefreshSelector(SELECTOR_TYPE.RECENT);
RefreshSelector(SELECTOR_TYPE.TRASH);
RefreshSelector(SELECTOR_TYPE.FAVORITE);
}
public static void RefreshAllSelectorsAsync() {
RefreshSelectorAsync(SELECTOR_TYPE.WORKSPACE);
RefreshSelectorAsync(SELECTOR_TYPE.SERVER);
RefreshSelectorAsync(SELECTOR_TYPE.PENDING);
RefreshSelectorAsync(SELECTOR_TYPE.RECENT);
RefreshSelectorAsync(SELECTOR_TYPE.TRASH);
RefreshSelectorAsync(SELECTOR_TYPE.FAVORITE);
}
public static void DeselectSelector(SELECTOR_TYPE type) {
var selector = GetSelector(type);
if (selector != null) selector.Model.IsSelected = false;
}
public static void DeselectAllSelectors() {
DeselectSelector(SELECTOR_TYPE.WORKSPACE);
DeselectSelector(SELECTOR_TYPE.SERVER);
DeselectSelector(SELECTOR_TYPE.PENDING);
DeselectSelector(SELECTOR_TYPE.RECENT);
DeselectSelector(SELECTOR_TYPE.TRASH);
DeselectSelector(SELECTOR_TYPE.FAVORITE);
}
public static void RefreshView() {
var main = App.Current.MainWindow as MainWindow;
var selector = GetCurrentSelector();
if (selector != null) {
main.ViewPane.Content = selector.SidbebarView;
}
}
public static void RefreshCurrent() {
var selector = GetCurrentSelector();
if (selector != null) {
selector.Model.Refresh();
}
}
///
/// Locates all children of a particular type
///
/// The datatype of the child in the search
/// The parent dependency object
///
public static IEnumerable FindVisualChildren(DependencyObject depObj) where T : DependencyObject {
if (depObj != null) {
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) {
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T) {
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren(child)) {
yield return childOfChild;
}
}
}
}
public static void ScrollToRight() {
MainWindow main = App.Current.MainWindow as MainWindow;
main.ViewPane.ScrollToRightEnd();
}
public static void CriticalError(Exception e) {
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => {
Utility.StopSyncWorker();
Utility.StopWatchdog();
System.IO.File.WriteAllText(@"error.txt", e.StackTrace);
var message = string.Format("Error details:\n{0}\n", e.Message);
var main = App.Current.MainWindow as MainWindow;
// try to show the error in a modal dialog, otherwise just show a message box
if (main != null && main.DialogManager != null) {
var dialog = main.DialogManager.CreateMessageDialog(message, Technewlogic.WpfDialogManagement.DialogMode.OkCancel);
dialog.OkText = "Restart";
dialog.CancelText = "Quit";
dialog.VerticalDialogAlignment = VerticalAlignment.Top;
dialog.Ok = () => {
System.Windows.Forms.Application.Restart();
System.Windows.Application.Current.Shutdown();
};
dialog.Cancel = () => {
System.Windows.Application.Current.Shutdown();
};
dialog.Show();
} else {
MessageBox.Show(e.Message);
System.Windows.Application.Current.Shutdown();
}
}));
}
public static void ShowMessage(string message, bool shutdown = false) {
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => {
var main = App.Current.MainWindow as MainWindow;
var dialog = main.DialogManager.CreateMessageDialog(message, Technewlogic.WpfDialogManagement.DialogMode.Ok);
dialog.VerticalDialogAlignment = VerticalAlignment.Top;
if (shutdown) {
dialog.Ok = () => { App.Current.Shutdown(); };
}
dialog.Show();
}));
}
public static void ShowTimedMessage(string message, double timeout = 3d) {
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => {
var main = App.Current.MainWindow as MainWindow;
var form = new TimedMessageLabel(message, timeout);
var dialog = main.DialogManager.CreateCustomContentDialog(form, Technewlogic.WpfDialogManagement.DialogMode.None);
form.ParentDialog = dialog;
dialog.Show();
}));
}
public static void OpenWithApplication(string filename, string extension) {
var main = App.Current.MainWindow as MainWindow;
var form = new ChooseApplicationForm();
var dialog = main.DialogManager.CreateCustomContentDialog(form, Technewlogic.WpfDialogManagement.DialogMode.OkCancel);
form.ParentDialog = dialog;
dialog.VerticalDialogAlignment = VerticalAlignment.Top;
dialog.OkText = "Choose";
dialog.Ok = () => { OnOpenWith(form, filename, extension); };
dialog.CanOk = false;
dialog.Cancel = OnOpenWithCancel;
dialog.Show();
}
private static void OnOpenWith(ChooseApplicationForm form, string filename, string extension) {
var appPath = form.Executable.Text;
if(!string.IsNullOrEmpty(appPath)) {
// add association to settings
var extHelper = Utility.GetExtensionHelper();
extHelper.SetMapping(extension, form.Executable.Text);
extHelper.SaveMappings();
CommandHelper.OpenLocalFile(filename);
}
}
private static void OnOpenWithCancel() {
// cancelled choice
}
public static string GetFolderIcon(bool selected=false, bool mapped=false, bool inClientView=false, bool ignored=false, bool mixed=false) {
StringBuilder builder = new StringBuilder("Folder");
if (ignored) {
builder.Append("Ignored");
} else {
if (mapped) {
builder.Append("Mapped");
} else if(inClientView) {
builder.Append("Mixed");
} else {
builder.Append("Untracked");
}
}
//if (selected) builder.Append("Selected");
return GetIconURI(builder.ToString());
}
public static string GetFileIcon(bool selected = false, FileMetaData metadata = null) {
StringBuilder builder = new StringBuilder("File");
if(metadata != null) {
var other = string.Empty;
var action = metadata.Action;
if (metadata.OtherActions != null && metadata.OtherActions.Count > 0) {
other = "Other";
action = metadata.OtherActions[0];
}
switch (action) {
case FileAction.None:
if (!metadata.IsMapped) {
builder.Append("Untracked");
}
break;
case FileAction.Add:
builder.Append("Add");
break;
case FileAction.Edit:
builder.Append("Edit");
break;
case FileAction.Delete:
builder.Append("Delete");
break;
case FileAction.Move:
builder.Append("Move");
break;
case FileAction.MoveAdd:
builder.Append("MoveAdd");
break;
case FileAction.MoveDelete:
builder.Append("MoveDelete");
break;
}
builder.Append(other);
}
return GetIconURI(builder.ToString());
}
private static XElement _defaultIcons;
public static string GetDefaultIcon(string extension) {
string iconURI = Constants.DEFAULT_THUMBNAIL;
if (_defaultIcons == null) {
Assembly a = typeof(UIHelper).Assembly;
System.IO.Stream s = a.GetManifestResourceStream("Perforce.Resources.DefaultIcons.DefaultIconMapping.xml");
_defaultIcons = XElement.Load(s);
s.Close();
}
if (!string.IsNullOrEmpty(extension)) {
var selected = from cli in _defaultIcons.Elements("DefaultIcon")
where cli.Attribute("Extension").Value == extension
select cli.Attribute("Source").Value;
var array = selected.ToArray();
if (array.Length == 1) {
iconURI = array[0].ToString();
}
}
return iconURI;
}
private static XElement _mapping;
public static string GetIconURI(string name) {
string iconURI = null;
if (_mapping == null) {
Assembly a = typeof(UIHelper).Assembly;
System.IO.Stream s = a.GetManifestResourceStream("Perforce.Resources.ResourceMap.xml");
_mapping = XElement.Load(s);
s.Close();
}
var selected = from cli in _mapping.Elements("Mapping")
where cli.Attribute("Name").Value == name
select cli.Attribute("Value").Value;
var array = selected.ToArray();
if (array.Length == 1) {
iconURI = array[0].ToString();
}
return iconURI;
}
}
}