/// <summary> /// Loads the add-in menu and toolbar buttons /// </summary> /// <param name="window"></param> public void InitializeAddinsUi(MainWindow window, List <MarkdownMonsterAddin> addins = null) { if (addins == null) { addins = this.AddIns; } foreach (var addin in addins) { addin.Model = window.Model; foreach (var menuItem in addin.MenuItems) { try { var mitem = new MenuItem() { Header = menuItem.Caption, }; Action <object, ICommand> xAction = (s, c) => { try { menuItem.Execute?.Invoke(mitem); } catch (Exception ex) { mmApp.Log($"Addin {addin.Name ?? addin.Id} Execute failed", ex); string msg = $"The '{addin.Name ?? addin.Id}' addin failed:\r\n\r\n{ex.GetBaseException().Message}\r\n\r\n" + "You can check to see if there is an update for the Addin available in the Addin Manager. We also recommend you update to the latest version of Markdown Monster."; MessageBox.Show(msg, "Addin Execution Failed", MessageBoxButton.OK, MessageBoxImage.Warning); } }; Func <object, ICommand, bool> cxAction = null; if (menuItem.CanExecute != null) { cxAction = (s, e) => { try { return(menuItem.CanExecute.Invoke(s)); } catch (Exception ex) { mmApp.Log($"Addin {addin.Name} CanExecute failed", ex); return(true); } } } ; menuItem.Command = new CommandBase(xAction, cxAction); mitem.Command = menuItem.Command; // if an icon is provided also add to toolbar if (menuItem.FontawesomeIcon != FontAwesomeIcon.None || menuItem.IconImageSource != null) { var hasConfigMenu = menuItem.ExecuteConfiguration != null; var titem = new Button(); var source = menuItem.IconImageSource ?? ImageAwesome.CreateImageSource(menuItem.FontawesomeIcon, addin.Model.Window.Foreground); titem.Content = new Image() { Source = source, ToolTip = menuItem.Caption + (!string.IsNullOrEmpty(menuItem.KeyboardShortcut) ? $" ({menuItem.KeyboardShortcut})" : string.Empty), Height = menuItem.IconImageSource == null ? 18 : 19, Width = menuItem.IconImageSource == null ? 18 : 19, Margin = new Thickness(5, 0, hasConfigMenu ? 0 : 5, 0) }; if (menuItem.Execute != null) { titem.Command = menuItem.Command; AddKeyboardShortcut(menuItem, addin); } addin.Model.Window.ToolbarAddIns.Visibility = Visibility.Visible; int toolIndex = addin.Model.Window.ToolbarAddIns.Items.Add(titem); // Add configuration dropdown if configured if (hasConfigMenu) { var tcitem = new Button { FontSize = 10F, Content = new Image() { Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.CaretDown, addin.Model.Window.Foreground), Height = 16, Width = 8, Margin = new Thickness(0, 0, 0, 0), }, ToolTip = menuItem.Caption + " Configuration", }; var ctxm = new ContextMenu(); tcitem.ContextMenu = ctxm; // create context menu and add drop down behavior var behaviors = Interaction.GetBehaviors(tcitem); behaviors.Add(new DropDownButtonBehavior()); tcitem.Click += (sender, args) => { ctxm.Items.Clear(); var configMenuItem = new MenuItem() { Header = menuItem.Caption }; configMenuItem.Command = menuItem.Command; if (menuItem.CanExecute != null) { configMenuItem.IsEnabled = menuItem.CanExecute.Invoke(sender); } ctxm.Items.Add(configMenuItem); configMenuItem = new MenuItem() { Header = menuItem.Caption + " Configuration", }; if (menuItem.ExecuteConfiguration != null) { configMenuItem.Click += (s, e) => menuItem.ExecuteConfiguration?.Invoke(s); } ctxm.Items.Add(configMenuItem); }; addin.Model.Window.ToolbarAddIns.Items.Add(tcitem); } ; addin.Model.PropertyChanged += (s, arg) => { if (arg.PropertyName == "ActiveDocument" || arg.PropertyName == "ActiveEditor") { menuItem.Command?.InvalidateCanExecute(); // this shouldn't be necessary but it looks if the Command bindings work correctly //var item = addin.Model.Window.ToolbarAddIns.Items[toolIndex] as Button; //if (item != null) //{ // ((CommandBase)item.Command).InvalidateCanExecute(); // if (menuItem.CanExecute != null) // item.IsEnabled = menuItem.CanExecute.Invoke(null); //} } }; } } catch (Exception ex) { var msg = $"Unable to load add-in: {Path.GetFileNameWithoutExtension(addin.Name)}"; mmApp.Log(msg, ex); AddinLoadErrors.AppendLine(msg + "\r\n"); } } } if (AddinLoadErrors.Length > 0) { MessageBox.Show(AddinLoadErrors.ToString() + "\r\n\r\n" + "Try updating each failing addin and Markdown Monster to the latest versions or uninstall each failing addins.", "The following addins failed to load", MessageBoxButton.OK, MessageBoxImage.Warning); } _addinLoadErrors = null; }
/// <summary> /// Loads the add-in menu and toolbar buttons /// </summary> /// <param name="window"></param> public void InitializeAddinsUi(MainWindow window, List <MarkdownMonsterAddin> addins = null) { if (addins == null) { addins = AddIns; } foreach (var addin in addins) { addin.Model = window.Model; foreach (var addinMenuItem in addin.MenuItems) { try { var mitem = new MenuItem { Header = addinMenuItem.Caption, Name = StringUtils.ToCamelCase(addinMenuItem.Caption) }; if (string.IsNullOrEmpty(addin.Name)) { addin.Name = addinMenuItem.Caption; } Action <object, ICommand> xAction = (s, c) => { try { addinMenuItem.Execute?.Invoke(mitem); } catch (Exception ex) { mmApp.Log($"Addin {addin.Name ?? addin.Id} Execute failed", ex); string msg = $"The '{addin.Name ?? addin.Id}' addin failed:\r\n\r\n{ex.GetBaseException().Message}\r\n\r\n" + "You can check to see if there is an update for the Addin available in the Addin Manager. We also recommend you update to the latest version of Markdown Monster."; MessageBox.Show(msg, "Addin Execution Failed", MessageBoxButton.OK, MessageBoxImage.Warning); } }; Func <object, ICommand, bool> cxAction = null; if (addinMenuItem.CanExecute != null) { cxAction = (s, e) => { try { return(addinMenuItem.CanExecute.Invoke(s)); } catch (Exception ex) { mmApp.Log($"Addin {addin.Name} CanExecute failed", ex); return(true); } } } ; addinMenuItem.Command = new CommandBase(xAction, cxAction); mitem.Command = addinMenuItem.Command; addin.Model.Window.MenuAddins.Items.Add(mitem); // if an icon is provided also add to toolbar if (addinMenuItem.FontawesomeIcon != FontAwesomeIcon.None || addinMenuItem.IconImageSource != null) { var hasConfigMenu = addinMenuItem.ExecuteConfiguration != null; Brush colorBrush; if (string.IsNullOrEmpty(addinMenuItem.FontawesomeIconColor)) { colorBrush = mmApp.Model.Window.Foreground; } else { colorBrush = new BrushConverter().ConvertFrom(addinMenuItem.FontawesomeIconColor) as Brush; } var titem = new Button(); var source = addinMenuItem.IconImageSource ?? ImageAwesome.CreateImageSource(addinMenuItem.FontawesomeIcon, colorBrush); titem.Content = new Image() { Source = source, ToolTip = addinMenuItem.Caption + (!string.IsNullOrEmpty(addinMenuItem.KeyboardShortcut) ? $" ({addinMenuItem.KeyboardShortcut})" : string.Empty), Height = addinMenuItem.IconImageSource == null ? 18 : 19, Width = addinMenuItem.IconImageSource == null ? 18 : 19, Margin = new Thickness(5, 0, hasConfigMenu ? 0 : 5, 0) }; addinMenuItem.MenuItemButton = titem; if (addinMenuItem.Execute != null) { titem.Command = addinMenuItem.Command; AddKeyboardShortcut(addinMenuItem, addin); } addin.Model.Window.ToolbarAddIns.Visibility = Visibility.Visible; int toolIndex = addin.Model.Window.ToolbarAddIns.Items.Add(titem); // Add configuration dropdown if configured if (hasConfigMenu) { var tcitem = new Button { FontSize = 10F, Content = new Image() { Source = ImageAwesome.CreateImageSource(FontAwesomeIcon.CaretDown, addin.Model.Window.Foreground), Height = 16, Width = 8, Margin = new Thickness(0, 0, 0, 0), }, ToolTip = addinMenuItem.Caption + " Configuration", }; var ctxm = new ContextMenu(); tcitem.ContextMenu = ctxm; // create context menu and add drop down behavior var behaviors = Interaction.GetBehaviors(tcitem); behaviors.Add(new DropDownButtonBehavior()); tcitem.Click += (sender, args) => { ctxm.Items.Clear(); var configMenuItem = new MenuItem() { Header = addinMenuItem.Caption }; configMenuItem.Command = addinMenuItem.Command; if (addinMenuItem.CanExecute != null) { configMenuItem.IsEnabled = addinMenuItem.CanExecute.Invoke(sender); } ctxm.Items.Add(configMenuItem); configMenuItem = new MenuItem() { Header = $"{addinMenuItem.Caption} Configuration", }; if (addinMenuItem.ExecuteConfiguration != null) { configMenuItem.Click += (s, e) => addinMenuItem.ExecuteConfiguration?.Invoke(s); } addinMenuItem.ConfigurationMenuItem = configMenuItem; ctxm.Items.Add(configMenuItem); // Uninstall Addin if (!addin.Id.Equals("screencapture", StringComparison.InvariantCultureIgnoreCase) && !addin.Id.Equals("weblog", StringComparison.InvariantCultureIgnoreCase) && !addin.Id.Equals("snippets", StringComparison.InvariantCultureIgnoreCase)) { configMenuItem = new MenuItem() { Header = $"Uninstall {addinMenuItem.Caption}", }; if (addinMenuItem.ExecuteConfiguration != null) { configMenuItem.Click += (s, e) => { if (AddinManager.Current.UninstallAddin(addin.Id)) { mmApp.Model.Window.ShowStatusSuccess( $"{addin.Name} addin has been removed."); addinMenuItem.MenuItemButton.Visibility = Visibility.Collapsed; tcitem.Visibility = Visibility.Collapsed; } else { mmApp.Model.Window.ShowStatusError( $"Unable to uninstall {addin.Name} addin."); } } } ; addinMenuItem.ConfigurationMenuItem = configMenuItem; ctxm.Items.Add(configMenuItem); } }; addin.Model.Window.ToolbarAddIns.Items.Add(tcitem); } ; } } catch (Exception ex) { var msg = $"Unable to load add-in: {Path.GetFileNameWithoutExtension(addin.Name)}"; mmApp.Log(msg, ex); AddinLoadErrors.AppendLine(msg + "\r\n"); } } } if (AddinLoadErrors.Length > 0) { MessageBox.Show(AddinLoadErrors.ToString() + "\r\n\r\n" + "Try updating each failing addin and Markdown Monster to the latest versions or uninstall each failing addins.", "The following addins failed to load", MessageBoxButton.OK, MessageBoxImage.Warning); } _addinLoadErrors = null; }