using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using InABox.Wpf.Editors; using Microsoft.Xaml.Behaviors.Core; namespace InABox.DynamicGrid { public class DynamicTabControlEventArgs : CancelEventArgs { public DynamicTabItem TabItem { get; set; } } public class DynamicTabItemContextMenuEventArgs : CancelEventArgs { public ContextMenu Menu { get; set; } } public class DynamicTabItemRenamedEventArgs : CancelEventArgs { public String OldName { get; set; } public String NewName { get; set; } } public delegate void DynamicTabControlChangedEvent(object sender, EventArgs args); public delegate void DynamicTabControlCreateEvent(object sender, DynamicTabControlEventArgs args); public delegate void DynamicTabItemCloseEvent(object sender, DynamicTabControlEventArgs args); public delegate void DynamicTabItemContextMenuEvent(object sender, DynamicTabItemContextMenuEventArgs args); public delegate void DynamicTabItemRenamedEvent(object sender, DynamicTabItemRenamedEventArgs args); public class DynamicTabControl : TabControl { public event DynamicTabControlChangedEvent OnTabsChanged; public static readonly DependencyProperty ChangedCommandProperty = DependencyProperty.Register(nameof(ChangedCommand), typeof(ICommand), typeof(DynamicTabControl)); public ICommand ChangedCommand { get { return base.GetValue(ChangedCommandProperty) as ICommand; } set { base.SetValue(ChangedCommandProperty, value); } } public event DynamicTabControlCreateEvent OnCreateTab; public static readonly DependencyProperty CreateTabCommandProperty = DependencyProperty.Register(nameof(CreateTabCommand), typeof(ICommand), typeof(DynamicTabControl)); public ICommand CreateTabCommand { get { return base.GetValue(CreateTabCommandProperty) as ICommand; } set { base.SetValue(CreateTabCommandProperty, value); } } public static readonly DependencyProperty CanCreateTabProperty = DependencyProperty.Register(nameof(CanCreateTab), typeof(bool), typeof(DynamicTabControl), new PropertyMetadata(false)); public bool CanCreateTab { get => (bool)GetValue(CanCreateTabProperty); set => SetValue(CanCreateTabProperty, value); } static DynamicTabControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicTabControl), new FrameworkPropertyMetadata(typeof(DynamicTabControl))); } public DynamicTabControl() : base() { ChangedCommand = new ActionCommand(() => OnTabsChanged?.Invoke(this, new EventArgs())); CanCreateTab = false; CreateTabCommand = new ActionCommand(() => { var args = new DynamicTabControlEventArgs() { TabItem = new DynamicTabItem() { Header = "New TabItem" }}; OnCreateTab?.Invoke(this, args); if (args.Cancel == false) { Items.Add(args.TabItem); ChangedCommand.Execute(null); } }); } protected override DependencyObject GetContainerForItemOverride() { return new DynamicTabItem(); } public static readonly DependencyProperty TabStripVisibleProperty = DependencyProperty.Register(nameof(TabStripVisible), typeof(bool), typeof(DynamicTabControl), new PropertyMetadata(true)); public bool TabStripVisible { get => (bool)GetValue(TabStripVisibleProperty); set { SetValue(TabStripVisibleProperty, value); Style s = new Style(); s.Setters.Add(new Setter(UIElement.VisibilityProperty, value ? Visibility.Visible : Visibility.Collapsed)); ItemContainerStyle = s; } } } public class DynamicTabItem : TabItem { public event DynamicTabItemCloseEvent OnCloseTab; public static readonly DependencyProperty CloseTabCommandProperty = DependencyProperty.Register(nameof(CloseTabCommand), typeof(ICommand), typeof(DynamicTabItem)); public ICommand CloseTabCommand { get { return base.GetValue(CloseTabCommandProperty) as ICommand; } set { base.SetValue(CloseTabCommandProperty, value); } } public static readonly DependencyProperty CanCloseProperty = DependencyProperty.Register(nameof(CanClose), typeof(bool), typeof(DynamicTabItem), new PropertyMetadata(false)); public bool CanClose { get => (bool)GetValue(CanCloseProperty); set => SetValue(CanCloseProperty, value); } public event DynamicTabItemContextMenuEvent OnContextMenuOpening; public static readonly DependencyProperty ContextMenuCommandProperty = DependencyProperty.Register(nameof(ContextMenuCommand), typeof(ICommand), typeof(DynamicTabItem)); public ICommand ContextMenuCommand { get { return base.GetValue(ContextMenuCommandProperty) as ICommand; } set { base.SetValue(ContextMenuCommandProperty, value); } } public static readonly DependencyProperty CanRenameProperty = DependencyProperty.Register(nameof(CanRename), typeof(bool), typeof(DynamicTabItem), new PropertyMetadata(false)); public bool CanRename { get => (bool)GetValue(CanRenameProperty); set => SetValue(CanRenameProperty, value); } /// /// Called when a tab is renamed. Note that changing will change the new name of the tab. /// public event DynamicTabItemRenamedEvent OnTabRenamed; static DynamicTabItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicTabItem), new FrameworkPropertyMetadata(typeof(DynamicTabItem))); } public DynamicTabItem() : base() { Height = 25; CloseTabCommand = new ActionCommand(() => { bool bConfirm = false; if (OnCloseTab != null) { var args = new DynamicTabControlEventArgs() { TabItem = this }; OnCloseTab?.Invoke(this, args); bConfirm = !args.Cancel; } else bConfirm = MessageBox.Show("Are you sure you wish to close this tab?", "Close Tab", MessageBoxButton.YesNo) == MessageBoxResult.Yes; if (bConfirm) { var parent = Parent as DynamicTabControl; if (parent != null) { parent.Items.Remove(this); parent.ChangedCommand.Execute(null); } } }); ContextMenuCommand = new ActionCommand(() => { ContextMenu menu = new ContextMenu(); if (CanRename) { menu.Items.Add(new MenuItem() { Header = "Rename Tab", Command = new ActionCommand(() => { String tabname = Header.ToString() ?? string.Empty; if (TextEdit.Execute("Rename Tab", ref tabname)) { var args = new DynamicTabItemRenamedEventArgs() { OldName = Header.ToString() ?? string.Empty, NewName = tabname }; OnTabRenamed?.Invoke(this, args); Header = args.NewName; var parent = Parent as DynamicTabControl; if (parent != null) parent.ChangedCommand.Execute(null); } }) }); } if (OnContextMenuOpening != null) { var args = new DynamicTabItemContextMenuEventArgs { Menu = menu }; OnContextMenuOpening.Invoke(this, args); if (args.Cancel == false) args.Menu.IsOpen = true; } else menu.IsOpen = CanRename; }); } } }