private static void InitializeContextMenuItem([NotNull] ButtonDefinition menuItemElement, ItemCollection itemCollection, MainWindow window, Func <string, ImageSource> getImage)
        {
            try
            {
                var header = menuItemElement.Label;
                if (string.IsNullOrEmpty(header))
                {
                    itemCollection.Add(new Separator());
                    return;
                }

                // create handler
                var mainWindowButton = menuItemElement.Handler;

                // create Context Menu Item
                var menuItem = new System.Windows.Controls.MenuItem
                {
                    Header = header,
                    Icon   = new Image
                    {
                        Source = getImage(menuItemElement.Image),
                        Width  = 16,
                        Height = 16
                    },
                    IsEnabled = mainWindowButton == null || mainWindowButton.IsEnabled(window, SelectedInstance),
                    Tag       = mainWindowButton
                };

                if (mainWindowButton != null)
                {
                    menuItem.Click += (obj, e) =>
                    {
                        try
                        {
                            if (mainWindowButton.IsEnabled(MainWindow.Instance, SelectedInstance))
                            {
                                mainWindowButton.OnClick(MainWindow.Instance, SelectedInstance);
                                RefreshInstances();
                            }
                        }
                        catch (Exception ex)
                        {
                            WindowHelper.HandleError("Failed to initialize context menu", true, ex);
                        }
                    };

                    SetIsEnabledProperty(menuItem, mainWindowButton);
                }

                foreach (var childElement in menuItemElement.Buttons ?? new ButtonDefinition[0])
                {
                    if (childElement == null)
                    {
                        continue;
                    }

                    InitializeContextMenuItem(childElement, menuItem.Items, window, getImage);
                }

                itemCollection.Add(menuItem);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Plugin Menu Item caused an exception");
            }
        }
        private static void InitializeRibbonButton(MainWindow window, Func <string, ImageSource> getImage, ButtonDefinition button, RibbonGroupBox ribbonGroup)
        {
            using (new ProfileSection("Initialize ribbon button"))
            {
                ProfileSection.Argument("button", button);
                ProfileSection.Argument("ribbonGroup", ribbonGroup);
                ProfileSection.Argument("window", window);
                ProfileSection.Argument("getImage", getImage);

                try
                {
                    // create handler
                    var mainWindowButton = button.Handler;

                    FrameworkElement ribbonButton;
                    ribbonButton = GetRibbonButton(window, getImage, button, ribbonGroup, mainWindowButton);

                    Assert.IsNotNull(ribbonButton, nameof(ribbonButton));

                    var    width = button.Width;
                    double d;
                    if (!string.IsNullOrEmpty(width) && double.TryParse(width, out d))
                    {
                        ribbonButton.Width = d;
                    }

                    // bind IsEnabled event
                    if (mainWindowButton != null)
                    {
                        ribbonButton.Tag       = mainWindowButton;
                        ribbonButton.IsEnabled = mainWindowButton.IsEnabled(window, SelectedInstance);
                        SetIsEnabledProperty(ribbonButton, mainWindowButton);
                    }
                }
                catch (Exception ex)
                {
                    WindowHelper.HandleError($"Plugin Button caused an exception: {button.Label}", true, ex);
                }
            }
        }
        private static FrameworkElement GetRibbonButton(MainWindow window, Func <string, ImageSource> getImage, ButtonDefinition button, RibbonGroupBox ribbonGroup, IMainWindowButton mainWindowButton)
        {
            Assert.ArgumentNotNull(button, nameof(button));
            Assert.ArgumentNotNull(ribbonGroup, nameof(ribbonGroup));

            var header = button.Label;

            var clickHandler = GetClickHandler(mainWindowButton);

            if (button.Buttons == null || button.Buttons.Length == 0 || button.Buttons.All(x => x == null))
            {
                // create Ribbon Button
                var imageSource  = getImage(button.Image);
                var fluentButton = new Fluent.Button
                {
                    Icon      = imageSource,
                    LargeIcon = imageSource,
                    Header    = header
                };
                fluentButton.Click += clickHandler;
                ribbonGroup.Items.Add(fluentButton);
                return(fluentButton);
            }

            // create Ribbon Button
            var splitButton = ribbonGroup.Items.OfType <SplitButton>().SingleOrDefault(x => x.Header.ToString().Trim().EqualsIgnoreCase(header.Trim()));

            if (splitButton == null)
            {
                var imageSource = getImage(button.Image);
                splitButton = new Fluent.SplitButton
                {
                    Icon      = imageSource,
                    LargeIcon = imageSource,
                    Header    = header
                };

                if (mainWindowButton != null)
                {
                    splitButton.Click += clickHandler;
                }
                else
                {
                    var childrenButtons = new List <KeyValuePair <string, IMainWindowButton> >();
                    splitButton.Tag    = childrenButtons;
                    splitButton.Click += (sender, args) => splitButton.IsDropDownOpen = true;
                }

                ribbonGroup.Items.Add(splitButton);
            }

            var items = splitButton.Items;

            Assert.IsNotNull(items, nameof(items));

            foreach (var menuItem in button.Buttons)
            {
                if (menuItem == null)
                {
                    continue;
                }

                try
                {
                    var menuHeader = menuItem.Label;
                    if (string.IsNullOrEmpty(menuHeader))
                    {
                        items.Add(new Separator());
                        continue;
                    }

                    var largeImage  = menuItem.Image;
                    var menuIcon    = string.IsNullOrEmpty(largeImage) ? null : getImage(largeImage);
                    var menuHandler = menuItem.Handler;

                    var childrenButtons = splitButton.Tag as ICollection <KeyValuePair <string, IMainWindowButton> >;
                    if (childrenButtons != null)
                    {
                        childrenButtons.Add(new KeyValuePair <string, IMainWindowButton>(menuHeader, menuHandler));
                    }

                    var menuButton = new Fluent.MenuItem()
                    {
                        Header    = menuHeader,
                        IsEnabled = menuHandler?.IsEnabled(window, SelectedInstance) ?? true
                    };

                    if (menuIcon != null)
                    {
                        menuButton.Icon = menuIcon;
                    }

                    if (menuHandler != null)
                    {
                        // bind IsEnabled event
                        SetIsEnabledProperty(menuButton, menuHandler);

                        menuButton.Click += delegate
                        {
                            try
                            {
                                if (menuHandler.IsEnabled(MainWindow.Instance, SelectedInstance))
                                {
                                    menuHandler.OnClick(MainWindow.Instance, SelectedInstance);
                                    RefreshInstances();
                                }
                            }
                            catch (Exception ex)
                            {
                                WindowHelper.HandleError($"Error during handling menu button click: {menuHandler.GetType().FullName}", true, ex);
                            }
                        };
                    }

                    items.Add(menuButton);
                }
                catch (Exception ex)
                {
                    WindowHelper.HandleError($"Error during initializing ribbon button: {menuItem.Label}", true, ex);
                }
            }

            return(splitButton);
        }