// // 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; } } }