public static void OnTemplateFilePreviewDrag(DragEventArgs dragEvent) { // Check the arguments for null ThrowIf.IsNullArgument(dragEvent, nameof(dragEvent)); if (DragDropFile.IsTemplateFileDragging(dragEvent, out _)) { dragEvent.Effects = DragDropEffects.All; } else { dragEvent.Effects = DragDropEffects.None; } dragEvent.Handled = true; }
/// <summary> /// Given two dictionaries, return a dictionary that contains only those key / value pairs in dictionary1 that are not in dictionary2 /// </summary> /// <param name="dictionary1"></param> /// <param name="dictionary2"></param> /// <returns></returns> public static Dictionary <string, string> Dictionary1ExceptDictionary2(Dictionary <string, string> dictionary1, Dictionary <string, string> dictionary2) { // Check the arguments for null ThrowIf.IsNullArgument(dictionary1, nameof(dictionary1)); ThrowIf.IsNullArgument(dictionary2, nameof(dictionary2)); Dictionary <string, string> dictionaryDifferences = new Dictionary <string, string>(); List <string> differencesByKeys = dictionary1.Keys.Except(dictionary2.Keys).ToList(); foreach (string key in differencesByKeys) { dictionaryDifferences.Add(key, dictionary1[key]); } return(dictionaryDifferences); }
/// <summary> /// Get a RecencyOrderedList from the registry /// </summary> public static RecencyOrderedList <string> GetRecencyOrderedList(this RegistryKey registryKey, string subKeyPath) { // Check the arguments for null ThrowIf.IsNullArgument(registryKey, nameof(registryKey)); RegistryKey subKey = registryKey.OpenSubKey(subKeyPath); RecencyOrderedList <string> values = new RecencyOrderedList <string>(Constant.Defaults.NumberOfMostRecentDatabasesToTrack); if (subKey != null) { for (int index = subKey.ValueCount - 1; index >= 0; --index) { string listItem = (string)subKey.GetValue(index.ToString()); if (listItem != null) { values.SetMostRecent(listItem); } } } return(values); }
// Try to load a layout from the given resourceFilePath private static bool AvalonLayout_TryLoadFromResource(this TimelapseWindow timelapse, string resourceFilePath) { // Check the arguments for null ThrowIf.IsNullArgument(timelapse, nameof(timelapse)); XmlLayoutSerializer serializer = new XmlLayoutSerializer(timelapse.DockingManager); Uri uri = new Uri(resourceFilePath); try { using (Stream stream = System.Windows.Application.GetResourceStream(uri).Stream) { serializer.Deserialize(stream); } } catch { // Should only happen if there is something wrong with the uri address, e.g., if the resource doesn't exist return(false); } return(true); }
/// <summary> /// If any dependency files are missing, return false else true /// </summary> public static bool AreRequiredBinariesPresent(string applicationName, Assembly executingAssembly) { // Check the arguments for null ThrowIf.IsNullArgument(executingAssembly, nameof(executingAssembly)); string directoryContainingCurrentExecutable = Path.GetDirectoryName(executingAssembly.Location); foreach (string binaryName in Dependencies.CommonRequiredBinaries) { if (File.Exists(Path.Combine(directoryContainingCurrentExecutable, binaryName)) == false) { return(false); } } if (applicationName == Constant.VersionUpdates.ApplicationName) { foreach (string binaryName in Dependencies.TimelapseRequiredBinaries) { if (File.Exists(Path.Combine(directoryContainingCurrentExecutable, binaryName)) == false) { return(false); } } } else { foreach (string binaryName in Dependencies.EditorRequiredBinaries) { if (File.Exists(Path.Combine(directoryContainingCurrentExecutable, binaryName)) == false) { return(false); } } } return(true); }
/// <summary> /// Sort the given data grid by the given column number in ascending order /// </summary> public static void SortByColumnAscending(this DataGrid dataGrid, int columnNumber) { // Check the arguments for null ThrowIf.IsNullArgument(dataGrid, nameof(dataGrid)); // Clear current sort descriptions dataGrid.Items.SortDescriptions.Clear(); // Add the new sort description DataGridColumn firstColumn = dataGrid.Columns[columnNumber]; ListSortDirection sortDirection = ListSortDirection.Ascending; dataGrid.Items.SortDescriptions.Add(new SortDescription(firstColumn.SortMemberPath, sortDirection)); // Apply sort foreach (DataGridColumn column in dataGrid.Columns) { column.SortDirection = null; } firstColumn.SortDirection = sortDirection; // Refresh items to display sort dataGrid.Items.Refresh(); }
/// <summary> /// Write a TimeSpan value as Seconds to registry /// </summary> public static void Write(this RegistryKey registryKey, string subKeyPath, TimeSpan value) { // Check the arguments for null ThrowIf.IsNullArgument(registryKey, nameof(registryKey)); registryKey.SetValue(subKeyPath, value.TotalSeconds.ToString(), RegistryValueKind.String); }
/// <summary> /// Write a string value to registry /// </summary> public static void Write(this RegistryKey registryKey, string subKeyPath, string value) { // Check the arguments for null ThrowIf.IsNullArgument(registryKey, nameof(registryKey)); registryKey.SetValue(subKeyPath, value, RegistryValueKind.String); }
/// <summary> /// Try to load the layout identified by the layoutKey, which, depending on the key, is stored in the resource file or the registry /// This includes various adjustments, as detailed in the comments below. /// </summary> /// <param name="timelapse"></param> /// <param name="layoutKey"></param> /// <returns></returns> public static bool AvalonLayout_TryLoad(this TimelapseWindow timelapse, string layoutKey) { // Check the arguments for null ThrowIf.IsNullArgument(timelapse, nameof(timelapse)); bool isResourceFile = false; string layoutName = String.Empty; // Layouts are loaded from either the registry or from a resource file // If from the registry, then the registry lookup key is the the layoutKey // If from the resource file, then we have to use the path of the resource file switch (layoutKey) { case Constant.AvalonLayoutTags.DataEntryOnTop: layoutName = Constant.AvalonLayoutResourcePaths.DataEntryOnTop; isResourceFile = true; break; case Constant.AvalonLayoutTags.DataEntryOnSide: layoutName = Constant.AvalonLayoutResourcePaths.DataEntryOnSide; isResourceFile = true; break; case Constant.AvalonLayoutTags.DataEntryFloating: layoutName = Constant.AvalonLayoutResourcePaths.DataEntryFloating; isResourceFile = true; break; default: layoutName = layoutKey; break; } bool result; try { if (isResourceFile) { // Load thelayout from the resource file result = timelapse.AvalonLayout_TryLoadFromResource(layoutName); } else { // Load both the layout and the window position/size from the registry result = timelapse.AvalonLayout_TryLoadFromRegistry(layoutName); if (result) { timelapse.AvalonLayout_LoadWindowPositionAndSizeFromRegistry(layoutName + Constant.AvalonDockValues.WindowRegistryKeySuffix); timelapse.AvalonLayout_LoadWindowMaximizeStateFromRegistry(layoutName + Constant.AvalonDockValues.WindowMaximizeStateRegistryKeySuffix); } } } catch { // If for some reason loading the avalon layout fails, catch that and then reload from scratch. // Note that if this is the result of a corrupt registry entry, // that will self-correct as that entry will be over-written with new values after we load and image set and exit. result = false; } if (result == false) { // We are trying to load the last-used layout, but there isn't one. As a fallback, // we use the default configuration as specified in the XAML: - all tiled with the data entry on top. // Eve so, we check to see if the window position and size were saved; if they aren't there, it defaults to a reasonable size and position. timelapse.AvalonLayout_LoadWindowPositionAndSizeFromRegistry(layoutName + Constant.AvalonDockValues.WindowRegistryKeySuffix); timelapse.AvalonLayout_LoadWindowMaximizeStateFromRegistry(layoutName + Constant.AvalonDockValues.WindowMaximizeStateRegistryKeySuffix); return(result); } // After deserializing, a completely new LayoutRoot object is created. // This means we have to reset various things so the documents in the new object behave correctly. // This includes resetting the callbacks to the DataGrid.IsActiveChanged timelapse.DataEntryControlPanel.PropertyChanging -= timelapse.LayoutAnchorable_PropertyChanging; timelapse.DataGridPane.IsActiveChanged -= timelapse.DataGridPane_IsActiveChanged; timelapse.AvalonDock_ResetAfterDeserialize(); timelapse.DataGridPane.IsActiveChanged += timelapse.DataGridPane_IsActiveChanged; timelapse.DataEntryControlPanel.PropertyChanging += timelapse.LayoutAnchorable_PropertyChanging; // Force an update to the DataGridPane if its visible, as the above doesn't trigger it if (timelapse.DataGridPane.IsVisible) { timelapse.DataGridPane_IsActiveChanged(true); } // Force an update to the DataEntryControlPanel if its visible, as the above doesn't trigger it timelapse.DataEntryControlPanel.IsVisible = true; // Special case for DataEntryFloating: // Reposition the floating window in the middle of the main window, but just below the top // Note that this assumes there is just a single floating window (which should be the case for this configuration) if (layoutKey == Constant.AvalonLayoutTags.DataEntryFloating) { if (timelapse.DockingManager.FloatingWindows.Any()) { // BUG. This doesn't work, although it used to in older versions of AvalonDock. // It seems we need to call Float() to get these positions to 'stick', as otherwise the positions are done // relative to the primary screen. But if we call Float, it crashes as PreviousParent is null (in Float) foreach (var floatingWindow in timelapse.DockingManager.FloatingWindows) { // We set the DataEntry Control Panel top / left as it remembers the values (i.e. so the layout will be saved correctly later) // If we set the floating window top/left directly, it won't remember those values as its just the view. timelapse.DataEntryControlPanel.FloatingTop = timelapse.Top + 100; timelapse.DataEntryControlPanel.FloatingLeft = timelapse.Left + ((timelapse.Width - floatingWindow.Width) / 2.0); } // This used to cause the above values to 'stick', but it no longer works. //timelapse.DataEntryControlPanel.Float(); } } return(true); }
/// <summary> /// Get a REG_SZ key's value from the registry /// </summary> public static string GetString(this RegistryKey registryKey, string subKeyPath) { // Check the arguments for null ThrowIf.IsNullArgument(registryKey, nameof(registryKey)); return((string)registryKey.GetValue(subKeyPath)); }