using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using InABox.Core; using Syncfusion.Windows.Controls.Input; namespace InABox.DynamicGrid { [Flags] public enum DynamicSplitPanelView { Master = 1, Detail = 2, Combined = 4 } public enum DynamicSplitPanelAnchor { Master, Detail } public class DynamicSplitPanelSettings : EventArgs { public DynamicSplitPanelView View { get; set; } public double AnchorWidth { get; set; } public double DetailHeight { get; set; } } public delegate void DynamicSplitPanelChanged(object sender, DynamicSplitPanelSettings e); public class DynamicSplitPanel : Control { public static readonly DependencyProperty AllowableViewsProperty = DependencyProperty.Register( nameof(AllowableViews), typeof(DynamicSplitPanelView), typeof(DynamicSplitPanel), new UIPropertyMetadata( DynamicSplitPanelView.Master | DynamicSplitPanelView.Combined | DynamicSplitPanelView.Detail )); public static readonly DependencyProperty ViewProperty = DependencyProperty.Register("View", typeof(DynamicSplitPanelView), typeof(DynamicSplitPanel), new UIPropertyMetadata(DynamicSplitPanelView.Detail)); public static readonly DependencyProperty AnchorProperty = DependencyProperty.Register(nameof(Anchor), typeof(DynamicSplitPanelAnchor), typeof(DynamicSplitPanel), new UIPropertyMetadata(DynamicSplitPanelAnchor.Master)); public static readonly DependencyProperty AnchorWidthProperty = DependencyProperty.Register(nameof(AnchorWidth), typeof(double), typeof(DynamicSplitPanel), new UIPropertyMetadata((double)300F)); public static readonly DependencyProperty MasterCaptionProperty = DependencyProperty.Register("MasterCaption", typeof(string), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty DetailCaptionProperty = DependencyProperty.Register("DetailCaption", typeof(string), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty MasterProperty = DependencyProperty.Register(nameof(Master), typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty DetailHeaderProperty = DependencyProperty.Register("DetailHeader", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty DetailProperty = DependencyProperty.Register("Detail", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); public static readonly DependencyProperty DetailHeightProperty = DependencyProperty.Register("DetailHeight", typeof(double), typeof(DynamicSplitPanel), new UIPropertyMetadata((double)200F)); public static readonly DependencyProperty SecondaryDetailProperty = DependencyProperty.Register("SecondaryDetail", typeof(FrameworkElement), typeof(DynamicSplitPanel), new UIPropertyMetadata(null)); private Button CombinedLeft; private Button CombinedRight; private Grid DetailGrid; private Label DetailsHeader; private Button DetailsOnly; private SfGridSplitter DetailSplitter; private Grid Grid; private Label MasterHeader; private Button MasterOnly; private SfGridSplitter Splitter; static DynamicSplitPanel() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DynamicSplitPanel), new FrameworkPropertyMetadata(typeof(DynamicSplitPanel))); } public DynamicSplitPanelView AllowableViews { get => (DynamicSplitPanelView)GetValue(AllowableViewsProperty); set { SetValue(AllowableViewsProperty, value); ConfigureScreen(); } } private bool IsViewAllowed(params DynamicSplitPanelView[] views) { foreach (var view in views) { if ((AllowableViews & view) == view) return true; } return false; } public DynamicSplitPanelView View { get => (DynamicSplitPanelView)GetValue(ViewProperty); set { SetValue(ViewProperty, value); ConfigureScreen(); } } public DynamicSplitPanelAnchor Anchor { get => (DynamicSplitPanelAnchor)GetValue(AnchorProperty); set { SetValue(AnchorProperty, value); ConfigureScreen(); } } public double AnchorWidth { get => (double)GetValue(AnchorWidthProperty); set { SetValue(AnchorWidthProperty, value); ConfigureScreen(); } } public string MasterCaption { get => (string)GetValue(MasterCaptionProperty); set => SetValue(MasterCaptionProperty, value); //MasterHeader.Content = value; } public string DetailCaption { get => (string)GetValue(DetailCaptionProperty); set => SetValue(DetailCaptionProperty, value); //DetailHeader.Content = value; } public FrameworkElement Header { get => (FrameworkElement)GetValue(HeaderProperty); set => SetValue(HeaderProperty, value); } public FrameworkElement Master { get => (FrameworkElement)GetValue(MasterProperty); set => SetValue(MasterProperty, value); } public FrameworkElement DetailHeader { get => (FrameworkElement)GetValue(DetailHeaderProperty); set => SetValue(DetailHeaderProperty, value); } public FrameworkElement Detail { get => (FrameworkElement)GetValue(DetailProperty); set => SetValue(DetailProperty, value); } public double DetailHeight { get => (double)GetValue(DetailHeightProperty); set { SetValue(DetailHeightProperty, value); ConfigureScreen(); } } public FrameworkElement SecondaryDetail { get => (FrameworkElement)GetValue(SecondaryDetailProperty); set => SetValue(SecondaryDetailProperty, value); } public event DynamicSplitPanelChanged OnChanged; private void RightClick(object sender, RoutedEventArgs e) { if (View == DynamicSplitPanelView.Detail) View = DynamicSplitPanelView.Combined; else if (View == DynamicSplitPanelView.Combined) View = DynamicSplitPanelView.Master; Changed(); } private void LeftClick(object sender, RoutedEventArgs e) { if (View == DynamicSplitPanelView.Master) View = DynamicSplitPanelView.Combined; else if (View == DynamicSplitPanelView.Combined) View = DynamicSplitPanelView.Detail; Changed(); } public bool IsMasterVisible() => View == DynamicSplitPanelView.Master || View == DynamicSplitPanelView.Combined; public bool IsDetailVisible() => View == DynamicSplitPanelView.Detail || View == DynamicSplitPanelView.Combined; private void ConfigureScreen() { CheckParts(); try { if (MasterHeader != null) MasterHeader.Content = MasterCaption; if (DetailsHeader != null) DetailsHeader.Content = DetailCaption; if (CombinedLeft != null) CombinedLeft.Visibility = View == DynamicSplitPanelView.Combined && AllowableViews.HasFlag(DynamicSplitPanelView.Master) ? Visibility.Visible : Visibility.Collapsed; if (CombinedRight != null) CombinedRight.Visibility = View == DynamicSplitPanelView.Combined && AllowableViews.HasFlag(DynamicSplitPanelView.Detail) ? Visibility.Visible : Visibility.Collapsed; if (Grid != null) { Grid.ColumnDefinitions[0].Width = (View == DynamicSplitPanelView.Detail) && (Master != null) && (IsViewAllowed(DynamicSplitPanelView.Combined,DynamicSplitPanelView.Master)) ? new GridLength(1.0F, GridUnitType.Auto) : new GridLength(0.0F, GridUnitType.Pixel); Grid.ColumnDefinitions[1].Width = Master == null ? new GridLength(0.0F, GridUnitType.Pixel) : View switch { DynamicSplitPanelView.Master => new GridLength(1.0F, GridUnitType.Star), DynamicSplitPanelView.Detail => new GridLength(0.0F, GridUnitType.Pixel), _ => Anchor == DynamicSplitPanelAnchor.Master ? new GridLength(AnchorWidth, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Star) }; Grid.ColumnDefinitions[2].Width = (View == DynamicSplitPanelView.Combined) && (Master != null) ? new GridLength(1.0F, GridUnitType.Auto) : new GridLength(0.0F, GridUnitType.Pixel); Grid.ColumnDefinitions[3].Width = View switch { DynamicSplitPanelView.Master => new GridLength(0.0F, GridUnitType.Pixel), DynamicSplitPanelView.Detail => new GridLength(1.0F, GridUnitType.Star), _ => Anchor == DynamicSplitPanelAnchor.Detail ? new GridLength(AnchorWidth, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Star) }; Grid.ColumnDefinitions[4].Width = (View == DynamicSplitPanelView.Master) && (IsViewAllowed(DynamicSplitPanelView.Combined,DynamicSplitPanelView.Detail)) ? new GridLength(1.0F, GridUnitType.Auto) : new GridLength(0.0F, GridUnitType.Pixel); Grid.RowDefinitions[0].Height = Header == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Auto); } if (DetailGrid != null) { DetailGrid.SetValue(Grid.RowProperty, DetailHeader == null ? 0 : 1); DetailGrid.SetValue(Grid.RowSpanProperty, DetailHeader == null ? 2 : 1); DetailGrid.RowDefinitions[0].Height = SecondaryDetail == null ? new GridLength(1.0F, GridUnitType.Star) : new GridLength(DetailHeight, GridUnitType.Pixel); DetailGrid.RowDefinitions[1].Height = SecondaryDetail == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Auto); DetailGrid.RowDefinitions[2].Height = SecondaryDetail == null ? new GridLength(0.0F, GridUnitType.Pixel) : new GridLength(1.0F, GridUnitType.Star); DetailSplitter.IsEnabled = SecondaryDetail != null; } if (CombinedRight != null) { CombinedRight.Visibility = (View == DynamicSplitPanelView.Combined) && IsViewAllowed(DynamicSplitPanelView.Master) ? Visibility.Visible : Visibility.Collapsed; } if (CombinedLeft != null) { CombinedLeft.Visibility = (View == DynamicSplitPanelView.Combined) && IsViewAllowed(DynamicSplitPanelView.Detail) ? Visibility.Visible : Visibility.Collapsed; } } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } } private void Splitter_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (Anchor == DynamicSplitPanelAnchor.Master) SetValue(AnchorWidthProperty, Grid.ColumnDefinitions[1].ActualWidth); else SetValue(AnchorWidthProperty, Grid.ColumnDefinitions[3].ActualWidth); SetValue(DetailHeightProperty, SecondaryDetail == null ? 0.0F : DetailGrid.RowDefinitions[0].ActualHeight); Changed(); } private void Changed() { OnChanged?.Invoke(this, new DynamicSplitPanelSettings { View = View, AnchorWidth = AnchorWidth, DetailHeight = DetailHeight }); } public override void OnApplyTemplate() { base.OnApplyTemplate(); CheckParts(); ConfigureScreen(); } private void CheckParts() { try { if (Grid == null) Grid = GetTemplateChild("PART_Grid") as Grid; if (DetailGrid == null) DetailGrid = GetTemplateChild("PART_DetailGrid") as Grid; if (MasterHeader == null) MasterHeader = GetTemplateChild("PART_MasterHeader") as Label; if (DetailsHeader == null) DetailsHeader = GetTemplateChild("PART_DetailHeader") as Label; if (Splitter == null) { Splitter = GetTemplateChild("PART_Splitter") as SfGridSplitter; if (Splitter != null) { Splitter.PreviewMouseUp += Splitter_PreviewMouseUp; Splitter.TargetUpdated += Splitter_TargetUpdated; } } if (DetailSplitter == null) { DetailSplitter = GetTemplateChild("PART_DetailSplitter") as SfGridSplitter; if (DetailSplitter != null) DetailSplitter.PreviewMouseUp += Splitter_PreviewMouseUp; } if (DetailsOnly == null) { DetailsOnly = GetTemplateChild("PART_DetailsOnly") as Button; if (DetailsOnly != null) DetailsOnly.Click += RightClick; } if (CombinedRight == null) { CombinedRight = GetTemplateChild("PART_CombinedRight") as Button; if (CombinedRight != null) CombinedRight.Click += RightClick; } if (CombinedLeft == null) { CombinedLeft = GetTemplateChild("PART_CombinedLeft") as Button; if (CombinedLeft != null) CombinedLeft.Click += LeftClick; } if (MasterOnly == null) { MasterOnly = GetTemplateChild("PART_MasterOnly") as Button; if (MasterOnly != null) MasterOnly.Click += LeftClick; } } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } } private void Splitter_TargetUpdated(object sender, DataTransferEventArgs e) { // } } }