| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 | using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Windows.Controls;using System.Windows.Media;using System.Windows.Threading;using InABox.Configuration;using InABox.Core;using InABox.DynamicGrid;namespace InABox.Wpf;public abstract class MasterDetailPanel<TMaster, TMasterGrid, TSettings> : MasterDetailPanel, IPanel<TMaster>    where TMaster : Entity, IRemotable, IPersistent, new()    where TMasterGrid : DynamicDataGrid<TMaster>, new()    where TSettings : BaseObject, IUserConfigurationSettings, IMasterDetailSettings, new(){        private DispatcherTimer? timer;    private readonly List<IMasterDetailPage<TMaster>> _pages = new();    private DateTime _lastselection = DateTime.MaxValue;    private int _currentPage = -1;    private readonly TMasterGrid _masterGrid;    private IDataModelSource? _modelsource;    protected TSettings Settings { get; private set; } = new();    private void LoadSettings()    {        Settings = new UserConfiguration<TSettings>().Load();        _splitPanel.AnchorWidth = Settings.AnchorWidth;        _splitPanel.View = Settings.ViewType;        AfterLoadSettings(Settings);    }        protected void SaveSettings()    {        BeforeSaveSettings(Settings);        Settings.AnchorWidth = _splitPanel.AnchorWidth;        Settings.ViewType = _splitPanel.View;        Settings.MasterID = _masterGrid.SelectedRows.FirstOrDefault()?.Get<TMaster, Guid>(x => x.ID) ?? Guid.Empty;        new UserConfiguration<TSettings>().Save(Settings);    }        protected abstract void CreatePages();    protected abstract void AfterLoadSettings(TSettings settings);    protected abstract void BeforeSaveSettings(TSettings settings);    protected abstract string MasterColumnsTag { get; }    public virtual string SectionName => SelectedPage?.DataModelSource()?.SectionName ?? MasterColumnsTag;    public abstract void CreateToolbarButtons(IPanelHost host);        protected override void DoSplitPanelChanged()    {        SaveSettings();        var newTag = GetMasterColumnsTag();        if (!String.Equals(_masterGrid.ColumnsTag, newTag))        {            _masterGrid.ColumnsTag = newTag;            _masterGrid.Refresh(true, true);        }    }    private string GetMasterColumnsTag()    {        var newTag = Settings.ViewType == DynamicSplitPanelView.Master            ? $"{MasterColumnsTag}:Master"            : $"{MasterColumnsTag}:Combined";        return newTag;    }    protected MasterDetailPanel()    {        _masterGrid = new TMasterGrid();        _masterGrid.OnSelectItem += MasterGrid_OnSelectItem;        _masterGrid.BeforeRefresh += MasterGrid_BeforeRefresh;        _masterGrid.AfterRefresh += MasterGrid_AfterRefresh;    }    public void Setup()    {        LoadSettings();                _masterGrid.ColumnsTag = GetMasterColumnsTag();                _splitPanel.Master = _masterGrid;        _splitPanel.MasterCaption = MasterCaption;        _splitPanel.DetailCaption = DetailCaption;        _header.Content = MasterCaption;                CreatePages();                timer = new DispatcherTimer();        timer.Tick += Timer_Tick;        timer.Interval = new TimeSpan(0, 0, 0, 0, 100);            }        protected void CreatePage<TPage>(Func<bool> isAllowed, string caption)         where TPage : class, IMasterDetailPage<TMaster>    {        if (isAllowed())        {            var header = new DynamicTabItem() { Header = caption };            _tabControl.Items.Add(header);            if (Activator.CreateInstance(typeof(TPage), header) is TPage page)                _pages.Add(page);        }    }    protected void CreatePage<TPage>(string caption)        where TPage : class, IMasterDetailPage<TMaster>    {        CreatePage<TPage>(() => true, caption);    }    public void Shutdown(CancelEventArgs? cancel)    {        if (timer != null)            timer.IsEnabled = false;    }        public void Refresh()    {        _masterGrid.Refresh(timer?.IsEnabled == false, true);        _lastselection = DateTime.MinValue;        if (timer != null)            timer.IsEnabled = true;    }        public DataModel DataModel(Selection selection)    {        if (_modelsource == null)        {            var row = _masterGrid.SelectedRows.FirstOrDefault();            var filter = row != null                ? new Filter<TMaster>(x => x.ID).IsEqualTo(row.Get<TMaster, Guid>(x => x.ID))                : new Filter<TMaster>().None();            return new AutoDataModel<TMaster>(filter);        }        return _modelsource.DataModel(selection);    }    public event DataModelUpdateEvent? OnUpdateDataModel;        public bool IsReady { get; set; }        protected IMasterDetailPage<TMaster>? SelectedPage => _pages.FirstOrDefault(x => x.Tab == _tabControl.SelectedTab);        public Dictionary<string, object[]> Selected()    {        return SelectedPage != null           ? SelectedPage.Selected()           : new Dictionary<string, object[]> { { typeof(TMaster).EntityName(), _masterGrid.SelectedRows } };    }    public void Heartbeat(TimeSpan time)    {    }        protected override void DoPagesChanged()    {        _lastselection = DateTime.MinValue;    }            private void Timer_Tick(object? sender, EventArgs e)    {        if (_lastselection < DateTime.Now.AddMilliseconds(-500) && !_masterGridRefreshing)        {            _lastselection = DateTime.MaxValue;            var master = _masterGrid.SelectedRows.FirstOrDefault()?.ToObject<TMaster>() ?? new TMaster();            var dataModelSource = SelectedPage?.Refresh(master);            if (_tabControl.SelectedIndex != _currentPage)            {                if(dataModelSource is not null)                {                    _modelsource = dataModelSource;                    OnUpdateDataModel?.Invoke(dataModelSource.SectionName, dataModelSource.DataModel(Selection.None));                }                _currentPage = _tabControl.SelectedIndex;            }        }    }        private bool _masterGridRefreshing;    private void MasterGrid_BeforeRefresh(object sender, BeforeRefreshEventArgs args)    {        _masterGridRefreshing = true;    }    private void MasterGrid_AfterRefresh(object sender, AfterRefreshEventArgs args)    {        _masterGrid.SelectedRows = Settings.MasterID == Guid.Empty            ? Array.Empty<CoreRow>()            : _masterGrid.Data.Rows.Where(r => r.Get<TMaster, Guid>(c => c.ID) == Settings.MasterID).ToArray();        _masterGridRefreshing = false;    }    private void MasterGrid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)    {        if (!_masterGridRefreshing)        {            _lastselection = DateTime.Now;            SaveSettings();        }    }    }public abstract class MasterDetailPanel : UserControl{    protected DynamicSplitPanel _splitPanel;    protected Label _header;    protected DynamicTabControl _tabControl;    protected abstract string MasterCaption { get; }    protected abstract string DetailCaption { get; }        protected MasterDetailPanel()    {        _splitPanel = new DynamicSplitPanel        {            View = DynamicSplitPanelView.Combined,            AnchorWidth = 300,            MasterCaption = MasterCaption,            DetailCaption = DetailCaption        };        _splitPanel.OnChanged += SplitPanel_OnChanged;        _header = new Label        {            HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,            VerticalContentAlignment = System.Windows.VerticalAlignment.Center,        };        _splitPanel.Header = new Border        {            BorderBrush = new SolidColorBrush(Colors.Gray),            BorderThickness = new System.Windows.Thickness(0.75),            Background = new SolidColorBrush(Colors.WhiteSmoke),            Height = 25,            Child = _header        };        _tabControl = new DynamicTabControl();        Grid.SetColumn(_tabControl, 2);        Grid.SetRow(_tabControl, 0);        Grid.SetRowSpan(_tabControl, 2);        _tabControl.SelectionChanged += Pages_OnChanged;        _tabControl.SeparatorMargin = 4;        _splitPanel.Detail = _tabControl;        Content = _splitPanel;    }    protected abstract void DoSplitPanelChanged();        private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)    {        DoSplitPanelChanged();    }    protected abstract void DoPagesChanged();        private void Pages_OnChanged(object sender, SelectionChangedEventArgs e)    {        if (Equals(e.Source, _tabControl))            DoPagesChanged();    }}
 |