using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using Comal.Classes;
using InABox.Clients;
using InABox.Configuration;
using InABox.Core;
using InABox.DynamicGrid;
using InABox.WPF;
using Microsoft.Win32;
using Syncfusion.UI.Xaml.Diagram;
namespace PRSDesktop
{
///
/// Interaction logic for OrganizationalChart.xaml
///
public partial class OrgChartPanel : UserControl, IPanel
{
private OrgChartSettings _settings;
private readonly OrgChartDataModel model = new();
public OrgChartPanel()
{
InitializeComponent();
if (Security.IsAllowed())
Layout.Items.Add("Employees");
if (Security.IsAllowed())
Layout.Items.Add("Positions");
if (Security.IsAllowed())
Layout.Items.Add("Job Roles");
Layout.Visibility = Layout.Items.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
LayoutLabel.Visibility = Layout.Visibility;
}
public event DataModelUpdateEvent OnUpdateDataModel;
public bool IsReady { get; set; }
private void SaveSettings()
{
//_settings.Zoom = Zoom.Value;
_settings.Appearance = (OrgChartAppearance)Appearance.SelectedIndex;
_settings.Layout = Equals(Layout.SelectedValue, "Employees")
? OrgChartLayout.Employee
: Equals(Layout.SelectedValue, "Positions")
? OrgChartLayout.Position
: OrgChartLayout.Role;
Task.Run(
() => { new UserConfiguration().Save(_settings); }
);
}
#region IPanel Support
public void CreateToolbarButtons(IPanelHost host)
{
}
public Dictionary Selected()
{
return new Dictionary();
}
public void Heartbeat(TimeSpan time)
{
}
public void Setup()
{
_settings = new UserConfiguration().Load();
Appearance.SelectedIndex = (int)_settings.Appearance;
model.Appearance = _settings.Appearance;
var layout = _settings.Layout == OrgChartLayout.Employee
? "Employees"
: _settings.Layout == OrgChartLayout.Position
? "Positions"
: "Job Roles";
Layout.SelectedValue = Layout.Items.Contains(layout) ? layout : Layout.Items[0];
model.Layout = _settings.Layout;
//Zoom.Value = _settings.Zoom;
diagram.DataContext = model;
(diagram.Info as IGraphInfo).ItemAdded += ApplyItemTemplate;
model.Active = true;
}
public void Shutdown()
{
}
public string SectionName => "Organisational Chart";
public DataModel DataModel(Selection selection)
{
return new BaseDataModel(null);
}
public void Refresh()
{
model.Refresh();
var graphinfo = diagram.Info as IGraphInfo;
graphinfo.Commands.FitToPage.Execute(null);
}
private void ApplyItemTemplate(object sender, ItemAddedEventArgs args)
{
var node = args.Item as NodeViewModel;
if (node == null)
return;
node.ContentTemplate = TemplateGenerator.CreateDataTemplate(() =>
{
var image = new Border
{
BorderBrush = new SolidColorBrush(Colors.Gray),
BorderThickness = new Thickness(0.75),
CornerRadius = new CornerRadius(25.0),
Width = 50,
Height = 50,
Margin = new Thickness(0, 0, 5, 0)
};
image.SetBinding(TagProperty, new Binding("ID"));
image.SetBinding(Border.BackgroundProperty, new Binding("Image"));
image.SetBinding(VisibilityProperty, new Binding("ImageVisible"));
image.SetValue(Grid.ColumnProperty, 0);
image.SetValue(Grid.RowProperty, 0);
image.SetValue(Grid.RowSpanProperty, 2);
image.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
var position = new Label();
position.FontWeight = FontWeights.DemiBold;
position.HorizontalContentAlignment = HorizontalAlignment.Center;
//description.Background = new SolidColorBrush(Colors.Blue);
position.VerticalContentAlignment = VerticalAlignment.Top;
position.SetBinding(TagProperty, new Binding("ID"));
position.SetBinding(ContentProperty, "Position");
position.SetValue(Grid.ColumnProperty, 1);
position.SetValue(Grid.RowProperty, 0);
var name = new Label();
//name.Background = new SolidColorBrush(Colors.Green);
name.HorizontalContentAlignment = HorizontalAlignment.Center;
name.VerticalContentAlignment = VerticalAlignment.Center;
name.SetBinding(TagProperty, new Binding("ID"));
name.SetBinding(ContentProperty, "Name");
name.Background = new SolidColorBrush(Colors.Transparent);
var nameborder = new Border
{
BorderBrush = new SolidColorBrush(Colors.Transparent),
BorderThickness = new Thickness(0.75),
CornerRadius = new CornerRadius(5.0),
Padding = new Thickness(0)
};
nameborder.SetValue(Grid.ColumnProperty, 1);
nameborder.SetValue(Grid.RowProperty, 1);
nameborder.SetBinding(TagProperty, new Binding("ID"));
nameborder.SetBinding(Border.BackgroundProperty, "WarningColor");
nameborder.Child = name;
var layout = new Grid();
layout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(25, GridUnitType.Pixel) });
layout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
layout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
layout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
layout.Children.Add(image);
layout.Children.Add(position);
layout.Children.Add(nameborder);
var border = new Border
{
MinWidth = 150,
BorderBrush = new SolidColorBrush(Colors.Gray),
BorderThickness = new Thickness(0.75),
CornerRadius = new CornerRadius(5.0),
Padding = new Thickness(5),
Child = layout
};
border.MouseDown += Border_MouseDown;
border.SetBinding(TagProperty, "ID");
border.SetBinding(Border.BackgroundProperty, "Color");
return border;
});
}
#endregion
#region Menu Actions
private void AddExistingItemClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as System.Tuple;
entry.Item2.ParentID = entry.Item1.ID;
entry.Item2.Visible = true;
UpdateItems(new[] { entry.Item2 });
}
private void CreateNewItemClick(object sender, RoutedEventArgs e)
{
var menu = sender as MenuItem;
var parent = menu.Tag as OrgChartEntry;
var entry = new OrgChartEntry { ParentID = parent != null ? parent.ID : Guid.Empty };
EditItem(entry);
}
private void EditItemClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as OrgChartEntry;
EditItem(entry);
}
private void RemoveItemClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as OrgChartEntry;
var updates = model.Data.Where(x => x.ParentID == entry.ID).ToList();
foreach (var child in updates)
child.ParentID = entry.ParentID;
entry.ParentID = Guid.Empty;
entry.Visible = false;
updates.Add(entry);
UpdateItems(updates);
}
private void ChanegColorClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as OrgChartEntry;
var color = ImageUtils.StringToColor(entry.Color);
if (ColorEdit.Execute("Change Color", ref color))
{
entry.Color = ImageUtils.ColorToString(color);
UpdateItems(new[] { entry });
}
}
private void StartNewTreeClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as OrgChartEntry;
entry.ParentID = Guid.Empty;
UpdateItems(new[] { entry });
}
private void MoveToClick(object sender, RoutedEventArgs e)
{
var entry = (sender as MenuItem).Tag as System.Tuple;
entry.Item1.ParentID = entry.Item2.ID;
UpdateItems(new[] { entry.Item1 });
}
private void EditItem(OrgChartEntry entry)
{
if (_settings.Layout == OrgChartLayout.Employee)
{
var employee = entry.ID == Guid.Empty
? new Employee()
: new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault();
if (employee != null)
{
if (employee.ID == Guid.Empty)
employee.OrgChart.ReportsTo.ID = entry.ID;
var bOK = new EmployeeGrid().EditItems(new[] { employee });
if (bOK)
model.Refresh();
}
else
{
MessageBox.Show("Unable to Locate Employee!");
}
}
else if (_settings.Layout == OrgChartLayout.Position)
{
var position = entry.ID == Guid.Empty
? new EmployeePosition()
: new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault();
if (position != null)
{
if (position.ID == Guid.Empty)
position.OrgChart.ReportsTo.ID = entry.ID;
var bOK = new DynamicDataGrid().EditItems(new[] { position });
if (bOK)
model.Refresh();
}
else
{
MessageBox.Show("Unable to Locate Position!");
}
}
else if (_settings.Layout == OrgChartLayout.Role)
{
var role = entry.ID == Guid.Empty
? new Role()
: new Client().Load(new Filter(x => x.ID).IsEqualTo(entry.ID)).FirstOrDefault();
if (role != null)
{
if (role.ID == Guid.Empty)
role.OrgChart.ReportsTo.ID = entry.ID;
var bOK = new DynamicDataGrid().EditItems(new[] { role });
if (bOK)
model.Refresh();
}
else
{
MessageBox.Show("Unable to Locate Role!");
}
}
}
private void UpdateItems(IEnumerable entries)
{
if (_settings.Layout == OrgChartLayout.Employee)
{
var updates = new List();
foreach (var entry in entries)
{
var update = new Employee();
update.ID = entry.ID;
update.OrgChart.ReportsTo.ID = entry.ParentID;
update.OrgChart.Color = entry.Color;
update.OrgChart.Visible = entry.Visible;
updates.Add(update);
}
using (new WaitCursor())
{
new Client().Save(updates, "Updated from Org Chart");
//model.Refresh();
}
}
else if (_settings.Layout == OrgChartLayout.Position)
{
var updates = new List();
foreach (var entry in entries)
{
var update = new EmployeePosition();
update.ID = entry.ID;
update.OrgChart.ReportsTo.ID = entry.ParentID;
update.OrgChart.Color = entry.Color;
update.OrgChart.Visible = entry.Visible;
updates.Add(update);
}
using (new WaitCursor())
{
new Client().Save(updates, "Updated from Org Chart");
//model.Refresh();
}
}
else if (_settings.Layout == OrgChartLayout.Role)
{
var updates = new List();
foreach (var entry in entries)
{
var update = new Role();
update.ID = entry.ID;
update.OrgChart.ReportsTo.ID = entry.ParentID;
update.OrgChart.Color = entry.Color;
update.OrgChart.Visible = entry.Visible;
updates.Add(update);
}
using (new WaitCursor())
{
new Client().Save(updates, "Updated from Org Chart");
//model.Refresh();
}
}
diagram.Visibility = Visibility.Collapsed;
model.Refresh();
diagram.Visibility = Visibility.Visible;
}
#endregion
#region Menu Setup
private void LoadNewItemsMenu(ItemsControl menu)
{
menu.Items.Clear();
var parent = menu.Tag as OrgChartEntry;
foreach (var entry in model.Data.Where(x => x.Visible == false))
{
var item = new MenuItem { Header = _settings.Layout == OrgChartLayout.Employee ? entry.Name : entry.Position };
item.Click += AddExistingItemClick;
item.Tag = new System.Tuple(parent, entry);
menu.Items.Add(item);
}
}
private void LoadMoveToOptions(OrgChartEntry current, MenuItem moveto)
{
foreach (var entry in model.Data.OrderBy(x => x.Name))
if (!model.Data.IsChildOf(entry, current))
{
var item = new MenuItem { Header = _settings.Layout == OrgChartLayout.Employee ? entry.Name : entry.Position };
item.Tag = new System.Tuple(current, entry);
item.Click += MoveToClick;
moveto.Items.Add(item);
}
if (moveto.Items.Count > 0 && current.ParentID != Guid.Empty)
moveto.Items.Add(new Separator());
if (current.ParentID != Guid.Empty)
{
var noone = new MenuItem { Header = "Start New Tree" };
noone.Click += StartNewTreeClick;
noone.Tag = current;
moveto.Items.Add(noone);
}
}
private void Diagram_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed && Security.IsAllowed())
{
var menu = new ContextMenu();
var additem = new MenuItem { Header = "Add Existing" };
LoadNewItemsMenu(additem);
additem.IsEnabled = additem.Items.Count > 0;
menu.Items.Add(additem);
menu.Items.Add(new Separator());
var createitem = new MenuItem { Header = "Create New" };
createitem.Click += CreateNewItemClick;
menu.Items.Add(createitem);
menu.IsOpen = true;
}
}
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.RightButton == MouseButtonState.Pressed && Security.IsAllowed())
{
var id = (Guid)(sender as Border).Tag;
var current = model.Data.FirstOrDefault(x => x.ID == id);
if (current == null)
return;
e.Handled = true;
if (e.ClickCount == 2)
{
EditItem(current);
}
else
{
var menu = new ContextMenu();
var moveto = new MenuItem { Header = "Move To.." };
menu.Items.Add(moveto);
LoadMoveToOptions(current, moveto);
var changecolor = new MenuItem { Header = "Change Color" };
changecolor.Click += ChanegColorClick;
changecolor.Tag = current;
menu.Items.Add(changecolor);
var edititem = new MenuItem { Header = "Edit Properties" };
edititem.Click += EditItemClick;
edititem.Tag = current;
menu.Items.Add(edititem);
menu.Items.Add(new Separator());
var additem = new MenuItem { Header = "Add Existing" };
menu.Items.Add(additem);
LoadNewItemsMenu(additem);
additem.IsEnabled = additem.Items.Count > 0;
var newitem = new MenuItem { Header = "Create New" };
newitem.Click += CreateNewItemClick;
menu.Items.Add(newitem);
menu.Items.Add(new Separator());
var removeitem = new MenuItem { Header = "Remove" };
removeitem.Click += RemoveItemClick;
removeitem.Tag = current;
menu.Items.Add(removeitem);
menu.IsOpen = true;
}
}
}
#endregion
#region Toolbar Actions
private void Zoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
if (diagram == null)
return;
//if (model.Active)
// SaveSettings();
var graphinfo = diagram.Info as IGraphInfo;
graphinfo.Commands.Zoom.Execute(new ZoomPositionParameter
{
ZoomCommand = ZoomCommand.Zoom,
ZoomTo = e.NewValue / 100
});
}
private void PrintButton_Click(object sender, RoutedEventArgs e)
{
if (diagram == null)
return;
diagram.PrintingService.ShowDialog = true;
diagram.PrintingService.Print();
}
private void ExportButton_Click(object sender, RoutedEventArgs e)
{
if (diagram == null)
return;
var dlg = new SaveFileDialog();
dlg.Filter = "PNG Files (*.png)|*.png|PDF Files (*.pdf)|*.pdf";
dlg.FilterIndex = 0;
dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dlg.FileName = Path.Combine(dlg.InitialDirectory, "Organizational Chart.png");
if (dlg.ShowDialog() == true)
{
var tempfile = Path.GetTempFileName();
var finalfile = Path.ChangeExtension(dlg.FileName, dlg.FilterIndex > 1 ? "pdf" : "png");
diagram.ExportSettings = new ExportSettings
{
IsSaveToXps = dlg.FilterIndex > 1,
FileName = dlg.FilterIndex > 1 ? tempfile : finalfile,
ExportMode = ExportMode.Content
};
diagram.Export();
if (dlg.FilterIndex > 1)
{
MessageBox.Show("PDF Functions broken .in .NET6");
return;
// XPSToPdfConverter converter = new XPSToPdfConverter();
// PdfDocument pdfDocument = converter.Convert(tempfile);
// pdfDocument.Save(finalfile);
// pdfDocument.Close(true);
// System.IO.File.Delete(tempfile);
}
Process.Start(finalfile);
}
}
private void Appearance_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (model.Active)
SaveSettings();
model.Appearance = (OrgChartAppearance)Appearance.SelectedIndex;
}
private void Layout_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (model.Active)
SaveSettings();
model.Layout = _settings != null ? _settings.Layout : OrgChartLayout.Employee;
}
#endregion
}
}