Beispiel #1
0
        /// <summary>
        /// Write a RecencyOrderedList value to registry
        /// </summary>
        public static void Write(this RegistryKey registryKey, string subKeyPath, RecencyOrderedList <string> values)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(registryKey, nameof(registryKey));

            if (values != null)
            {
                // create the key whose values represent elements of the list
                RegistryKey subKey = registryKey.OpenSubKey(subKeyPath, true);
                if (subKey == null)
                {
                    subKey = registryKey.CreateSubKey(subKeyPath);
                }

                // write the values
                int index = 0;
                foreach (string value in values)
                {
                    subKey.SetValue(index.ToString(), value);
                    ++index;
                }

                // remove any additional values when the new list is shorter than the old one
                int maximumValueName = subKey.ValueCount;
                for (; index < maximumValueName; ++index)
                {
                    subKey.DeleteValue(index.ToString());
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Write an int value to registry
        /// </summary>
        public static void Write(this RegistryKey registryKey, string subKeyPath, int value)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(registryKey, nameof(registryKey));

            registryKey.SetValue(subKeyPath, value, RegistryValueKind.DWord);
        }
Beispiel #3
0
        /// <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));
        }
        // Try to load a layout from the registry given the registry key
        private static bool AvalonLayout_TryLoadFromRegistry(this TimelapseWindow timelapse, string registryKey)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(timelapse, nameof(timelapse));

            // Retrieve the layout configuration from the registry
            string layoutAsString = timelapse.State.GetFromRegistry(registryKey);

            if (string.IsNullOrEmpty(layoutAsString))
            {
                return(false);
            }

            // Convert the string to a stream
            MemoryStream layoutAsStream = new MemoryStream();

            using (StreamWriter writer = new StreamWriter(layoutAsStream))
            {
                writer.Write(layoutAsString);
                writer.Flush();
                layoutAsStream.Position = 0;

                // Deserializa and load the layout
                XmlLayoutSerializer serializer = new XmlLayoutSerializer(timelapse.DockingManager);
                using (StreamReader streamReader = new StreamReader(layoutAsStream))
                {
                    serializer.Deserialize(streamReader);
                }
                return(true);
            }
        }
        /// <summary>
        /// Save the current Avalon layout to the registry under the given registry key
        /// and the current timelapse window position and size under the given registry key with the added suffix
        /// </summary>
        /// <param name="timelapse"></param>
        /// <param name="registryKey"></param>
        /// <returns>false if there are any issues</returns>
        public static bool AvalonLayout_TrySave(this TimelapseWindow timelapse, string registryKey)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(timelapse, nameof(timelapse));

            // Serialization normally creates a stream, so we have to do a few contortions to transform that stream into a string
            StringBuilder xmlText = new StringBuilder();

            using (XmlWriter xmlWriter = XmlWriter.Create(xmlText))
            {
                // Serialize the layout into a string
                XmlLayoutSerializer serializer = new XmlLayoutSerializer(timelapse.DockingManager);
                using (StringWriter stream = new StringWriter())
                {
                    serializer.Serialize(xmlWriter);
                }
                if (!String.IsNullOrEmpty(xmlText.ToString().Trim()))
                {
                    // Write the string to the registry under the given key name
                    timelapse.State.WriteToRegistry(registryKey, xmlText.ToString());
                    AvalonLayout_TrySaveWindowPositionAndSizeAndMaximizeState(timelapse, registryKey);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        /// <summary>
        /// Save the various window positions, size and mazimize state to the registry
        /// </summary>
        /// <param name="timelapse"></param>
        /// <param name="registryKey"></param>
        public static void AvalonLayout_TrySaveWindowPositionAndSizeAndMaximizeState(this TimelapseWindow timelapse, string registryKey)
        {
            // Check the arguments for null
            ThrowIf.IsNullArgument(timelapse, nameof(timelapse));

            timelapse.AvalonLayout_SaveWindowPositionAndSizeToRegistry(registryKey + Constant.AvalonDockValues.WindowRegistryKeySuffix);
            timelapse.AvalonLayout_SaveWindowMaximizeStateToRegistry(registryKey + Constant.AvalonDockValues.WindowMaximizeStateRegistryKeySuffix);
        }
 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;
 }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #11
0
        /// <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);
        }
Beispiel #12
0
        /// <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();
        }
Beispiel #13
0
 /// <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>
        /// 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);
        }