using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using InABox.Configuration; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF.Themes; using Microsoft.Xaml.Behaviors.Core; using Syncfusion.Windows.Tools.Controls; namespace PRSDesktop { public class UtilityDashboardSettings : UserConfigurationSettings { public UtilityDashboardSettings() { Dashboards = new Dictionary(); } public Dictionary Dashboards { get; set; } public int Selected { get; set; } public bool AutoHide { get; set; } } /// /// Interaction logic for UtilityDashboard.xaml /// public partial class UtilityDashboard : UserControl, IBasePanel { private Dictionary _dashboards = new(); private readonly Dictionary> _panels = new(); private class WidgetDashboardElement { public Type DashboardElement { get; set; } public Type Widget { get; set; } public Type Group { get; set; } public Type Properties { get; set; } public string GroupCaption { get; set; } public string WidgetCaption { get; set; } public Type[] SecurityTokens { get; set; } public WidgetDashboardElement(Type dashboardElement, Type widget, Type group, Type properties, Type[] securityTokens) { DashboardElement = dashboardElement; Widget = widget; Group = group; Properties = properties; SecurityTokens = securityTokens; GroupCaption = UtilityDashboard.GetCaption(group); WidgetCaption = UtilityDashboard.GetCaption(widget); } } private static List? _dashboardElements; private string CurrentDashboardName => ((DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString()) ?? string.Empty; private DynamicFormDesignGrid? CurrentDashboard => CurrentDashboardName != null ? _dashboards.GetValueOrDefault(CurrentDashboardName) : null; private UtilityDashboardSettings _settings = new(); public UtilityDashboard() { InitializeComponent(); } public bool IsReady { get; set; } public event DataModelUpdateEvent OnUpdateDataModel; public void CreateToolbarButtons(IPanelHost host) { } public string? SectionName => "Utility Dashboard"; public DataModel? DataModel(Selection selection) { return new EmptyDataModel(); } public void Heartbeat(TimeSpan time) { } private void SaveDashboard(string name, DynamicFormDesignGrid grid) { _settings.Dashboards[name] = grid.Form.SaveLayout(); if (IsReady) new UserConfiguration().Save(_settings); } private void SaveCurrentDashboard() { var name = CurrentDashboardName; if (name == null) return; var grid = CurrentDashboard; if (grid == null) return; SaveDashboard(name, grid); } private void ShutdownDashboard(string name, DynamicFormDesignGrid grid) { SaveDashboard(name, grid); foreach (var panel in _panels[grid]) { panel.Shutdown(); } _panels[grid].Clear(); } private void ShutdownDashboard() { var name = CurrentDashboardName; if (name == null) return; var grid = CurrentDashboard; if (grid == null) return; ShutdownDashboard(name, grid); } private void RefreshDashboard(string name) { if (!_dashboards.ContainsKey(name)) return; var grid = _dashboards[name]; if (_panels.ContainsKey(grid)) { foreach (var panel in _panels[grid]) panel.Refresh(); } } public void Refresh() { RefreshDashboard(CurrentDashboardName); } public Dictionary Selected() { return new Dictionary(); } public void Setup() { _settings = new UserConfiguration().Load(); if (_settings.Dashboards.Count == 0) _settings.Dashboards["New Dashboard"] = CreateForm("").SaveLayout(); foreach (var key in _settings.Dashboards.Keys) CreateTab(key); if (_settings.Selected >= -1 && _settings.Selected < DashboardsTab.Items.Count) DashboardsTab.SelectedIndex = _settings.Selected; //DashboardsTab.FullScreenMode = _settings.AutoHide ? FullScreenMode.ControlMode : FullScreenMode.None; } private void InitializeTab(DynamicTabItem tab) { tab.CanClose = true; tab.OnCloseTab += (sender, args) => { var name = args.TabItem.Header?.ToString(); if (name is null) return; _dashboards.Remove(name); _settings.Dashboards.Remove(name); DashboardsTab.ChangedCommand.Execute(null); }; tab.CanRename = true; tab.OnTabRenamed += (sender, args) => { var oldSettings = _settings.Dashboards[args.OldName]; _settings.Dashboards.Remove(args.OldName); if (_dashboards.TryGetValue(args.OldName, out var dashboard)) { _dashboards.Remove(args.OldName); _dashboards[args.NewName] = dashboard; _settings.Dashboards[args.NewName] = dashboard.Form.SaveLayout(); } else { _settings.Dashboards[args.NewName] = oldSettings; } }; tab.OnContextMenuOpening += (sender, args) => { String? name = (DashboardsTab.SelectedItem as DynamicTabItem)?.Header?.ToString(); if (String.IsNullOrEmpty(name)) return; DynamicFormDesignGrid grid = _dashboards[name]; var menu = args.Menu; menu.Items.Add(new Separator()); menu.Items.Add(new MenuItem() { Header = grid.Mode == FormMode.Preview ? "Design Mode" : "Close Design Mode", Command = new ActionCommand(() => { if (grid.Mode == FormMode.Designing) { grid.Mode = FormMode.Preview; SaveCurrentDashboard(); DashboardsTab.ChangedCommand.Execute(null); } else { ShutdownDashboard(); grid.Mode = FormMode.Designing; } }) }); }; } private void CreateTab(string key) { var tab = new DynamicTabItem() { Header = key }; InitializeTab(tab); DashboardsTab.Items.Add(tab); } private void AddDashboard(DynamicTabItem tab) { var name = "New Dashboard"; var i = 0; while (TabNameExists(name)) { i++; name = string.Format("New Dashboard ({0})", i); } _settings.Dashboards[name] = CreateForm("").SaveLayout(); DashboardsTab.ChangedCommand.Execute(null); new UserConfiguration().Save(_settings); tab.Header = name; InitializeTab(tab); } private void DashboardsTab_OnOnCreateTab(object sender, DynamicTabControlEventArgs args) { AddDashboard(args.TabItem); } public void Shutdown() { foreach (var (name, grid) in _dashboards) { ShutdownDashboard(name, grid); } _panels.Clear(); } private FrameworkElement CreateElement(DynamicFormDesignGrid grid, DFLayoutElement element) where TWidget : FrameworkElement, IDashboardWidget, new() where TGroup : DashboardWidgetGroup where TProperties : IDashboardProperties, new() { if (!_panels.ContainsKey(grid)) _panels[grid] = new List(); var dashboardName = GetDashboardElements() .Where(x => x.DashboardElement == element.GetType()) .FirstOrDefault()?.WidgetCaption ?? "Unknown Dashboard"; var container = DashboardContainer.Create(element, dashboardName); _panels[grid].Add(container.Panel); return container; } private FrameworkElement OnCreateElement(object sender, DynamicFormCreateElementArgs e) { var widgetType = GetVisibleDashboardElements().Where(x => x.DashboardElement == e.Element.GetType()).FirstOrDefault(); if(widgetType == null) { var border = new Border(); border.BorderBrush = new SolidColorBrush(Colors.Gray); border.BorderThickness = new Thickness(0.0); border.Margin = new Thickness(0.0); border.Background = ThemeManager.WorkspaceBackgroundBrush; //new SolidColorBrush(Colors.Silver); return border; } var method = typeof(UtilityDashboard) .GetMethod(nameof(CreateElement), BindingFlags.Instance | BindingFlags.NonPublic) .MakeGenericMethod(widgetType.Widget, widgetType.Group, widgetType.Properties); return method.Invoke(this, new object[] { sender, e.Element }) as FrameworkElement; } private bool TabNameExists(string name) { return _settings.Dashboards.ContainsKey(name); } private static string GetCaption(Type groupType) { var caption = groupType.GetCustomAttribute(); if(caption != null) { return caption.Text; } return CoreUtils.Neatify(groupType.Name); } private static List GetDashboardElements() { if (_dashboardElements == null) { _dashboardElements = new(); var types = CoreUtils.TypeList( AppDomain.CurrentDomain.GetAssemblies(), x => x.IsClass && !x.IsAbstract && !x.IsGenericType); foreach (var type in types) { var dashboardElementDef = type.GetSuperclassDefinition(typeof(DashboardElement<,,>)); if (dashboardElementDef != null) { var dashboard = dashboardElementDef.GenericTypeArguments[0]; var group = dashboardElementDef.GenericTypeArguments[1]; var properties = dashboardElementDef.GenericTypeArguments[2]; var requires = dashboard.GetInterfaces(typeof(IRequiresSecurity<>)).Select(x => x.GenericTypeArguments[0]); _dashboardElements.Add(new(type, dashboard, group, properties, requires.ToArray())); } } } return _dashboardElements; } private static IEnumerable GetVisibleDashboardElements() { return GetDashboardElements().Where(x => { foreach (var require in x.SecurityTokens) { if (!Security.IsAllowed(require)) return false; } return true; }); } private Border CreateDashboard(string name, string layout) { var form = CreateForm(layout); var grid = new DynamicFormDesignGrid(); foreach(var widget in GetVisibleDashboardElements()) { grid.AddElement(widget.DashboardElement, widget.WidgetCaption, widget.GroupCaption, true); } grid.ShowBorders = false; grid.OnCreateElement += OnCreateElement; grid.OnAfterDesign += OnAfterDesign; grid.OnAfterRender += OnAfterRender; grid.Mode = FormMode.Preview; var border = new Border(); border.BorderBrush = new SolidColorBrush(Colors.Silver); border.BorderThickness = new Thickness(0.75); border.Child = grid; // scroll; _dashboards[name] = grid; _panels[grid] = new List(); grid.Form = form; grid.Initialize(); return border; } private void OnAfterRender(DynamicFormDesignGrid sender) { if (!sender.IsDesigning) { if (_panels.TryGetValue(sender, out var panels)) { foreach (var panel in panels) panel.Refresh(); } } } private static DFLayout CreateForm(string layout) { var form = new DFLayout(); if (string.IsNullOrWhiteSpace(layout)) { form.ColumnWidths.Add("*"); form.ColumnWidths.Add("*"); form.ColumnWidths.Add("*"); form.RowHeights.Add("*"); form.RowHeights.Add("*"); form.RowHeights.Add("*"); } else { form.LoadLayout(layout); } return form; } private void OnAfterDesign(object sender) { SaveCurrentDashboard(); RefreshDashboard(CurrentDashboardName); } private void DashboardsTab_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 0) return; ShutdownDashboard(); var tab = e.AddedItems[0] as DynamicTabItem; if (tab != null) { var name = (tab.Header as string)!; if (tab!.Content == null) tab.Content = CreateDashboard(name, _settings.Dashboards[name]); RefreshDashboard(name); if (IsReady) { _settings.Selected = tab.TabIndex; DashboardsTab.ChangedCommand.Execute(null); } } } private void DashboardsTab_OnOnTabsChanged(object sender, EventArgs args) { new UserConfiguration().Save(_settings); } } }