using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using Comal.Classes; using InABox.Clients; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Syncfusion.UI.Xaml.Diagram; using Syncfusion.UI.Xaml.Diagram.Stencil; namespace PRSDesktop { public class CustomDiagram : SfDiagram { public Selector SFSelector = new(); // Customising the grab handles for nodes added to the diagram public CustomDiagram() { SFSelector.Style = Application.Current.MainWindow.Resources["CustomSelectorStyle"] as Style; } protected override Selector GetSelectorForItemOverride(object item) { return SFSelector; } // Preventing Auto Connector creation when dragging from a port protected override void SetTool(SetToolArgs args) { if (args.Source is IPort) args.Action = ActiveTool.None; else base.SetTool(args); } } /// /// Interaction logic for QuoteDiagram.xaml /// public partial class QuoteDiagramControl : UserControl { private QuoteDiagram _diagram; private bool _disablesave; private BitmapImage _image; public QuoteDiagramControl() { InitializeComponent(); (diagram.PageSettings.Unit as LengthUnit).Unit = LengthUnits.Centimeters; } public QuoteDiagram Diagram { get => _diagram; set { _diagram = value; areas.SymbolSource = QuoteDiagramSymbolCache.Areas; symbols.SymbolSource = QuoteDiagramSymbolCache.Symbols; connectors.SymbolSource = QuoteDiagramSymbolCache.Connectors; diagram.Nodes = new NodeCollection(); diagram.Connectors = new ConnectorCollection(); //diagram.Page.Background = new SolidColorBrush(Colors.Yellow); diagram.SelectedItems = new SelectorViewModel { SelectorConstraints = SelectorConstraints.Resizer | SelectorConstraints.Rotator }; LoadDiagram(); } } public BitmapImage Image { get => _image; set { _image = value; diagram.PageSettings.PageHeight = _image != null ? _image.Height / LengthUnit.Centimeters : 29.7; diagram.PageSettings.PageWidth = _image != null ? _image.Width / LengthUnit.Centimeters : 21.0; diagram.PageSettings.PageBackground = new ImageBrush(value); } } private static void LoadAreaContent(QuoteDiagramAreaModel area, string id) { var cache = QuoteDiagramSymbolCache.Areas.FirstOrDefault(x => Equals(x.ID, area.Key)); if (cache != null) { area.Key = cache.ID; area.ContentTemplate = cache.ContentTemplate; } } private static void LoadSymbolContent(QuoteDiagramSymbolModel symbol, string id) { var cache = QuoteDiagramSymbolCache.Symbols.FirstOrDefault(x => Equals(x.ID, symbol.Key)); if (symbol != null) { symbol.Key = cache.ID; symbol.ContentTemplate = cache.ContentTemplate; } } private static void LoadConnectorContent(QuoteDiagramConnectorModel connector, string id) { var cache = QuoteDiagramSymbolCache.Connectors.FirstOrDefault(x => Equals(id, x.ID)); if (cache != null) { connector.Key = cache.ID; connector.ConnectorGeometryStyle = cache.ConnectorGeometryStyle; connector.CornerRadius = cache.CornerRadius; } } private void SaveDiagram() { if (_disablesave) return; using (var ms = new MemoryStream()) { var background = diagram.PageSettings.PageBackground; diagram.PageSettings.PageBackground = new SolidColorBrush(Colors.White); (diagram.Info as IGraphInfo).Save(ms); diagram.PageSettings.PageBackground = background; Diagram.Data = Encoding.UTF8.GetString(ms.ToArray()); new Client().Save(Diagram, "", (d, err) => { }); } } private void DoLoadDiagram() { var connectors = diagram.Connectors as ConnectorCollection; connectors.Clear(); var nodes = diagram.Nodes as NodeCollection; nodes.Clear(); if (Diagram != null && !string.IsNullOrWhiteSpace(Diagram.Data)) { var bytes = Encoding.UTF8.GetBytes(Diagram.Data); try { using (var ms = new MemoryStream(bytes)) { (diagram.Info as IGraphInfo).Load(ms); } foreach (var node in nodes) if (node is QuoteDiagramSymbolModel) LoadSymbolContent(node as QuoteDiagramSymbolModel, node.Key.ToString()); else if (node is QuoteDiagramAreaModel) LoadAreaContent(node as QuoteDiagramAreaModel, node.Key.ToString()); } catch (Exception e) { MessageBox.Show("Error Loading Diagram"); } } } private void LoadDiagram() { (diagram.Info as IGraphInfo).ItemAdded -= ItemAddedEvent; (diagram.Info as IGraphInfo).ItemTappedEvent -= Diagram_ItemTappedEvent; (diagram.Info as IGraphInfo).ConnectorSourceChangedEvent -= QuoteDiagramControl_ConnectorSourceChangedEvent; (diagram.Info as IGraphInfo).ConnectorTargetChangedEvent -= QuoteDiagramControl_ConnectorTargetChangedEvent; (diagram.Info as IGraphInfo).ItemSelectedEvent -= QuoteDiagramControl_ItemSelectedEvent; (diagram.Info as IGraphInfo).ItemUnSelectedEvent -= QuoteDiagramControl_ItemUnSelectedEvent; (diagram.Info as IGraphInfo).HistoryChangedEvent -= Diagram_HistoryChangedEvent; diagram.Constraints = GraphConstraints.Default; DoLoadDiagram(); CheckScalers(); (diagram.Info as IGraphInfo).ItemAdded += ItemAddedEvent; (diagram.Info as IGraphInfo).ItemTappedEvent += Diagram_ItemTappedEvent; (diagram.Info as IGraphInfo).HistoryChangedEvent += Diagram_HistoryChangedEvent; (diagram.Info as IGraphInfo).ConnectorSourceChangedEvent += QuoteDiagramControl_ConnectorSourceChangedEvent; (diagram.Info as IGraphInfo).ConnectorTargetChangedEvent += QuoteDiagramControl_ConnectorTargetChangedEvent; (diagram.Info as IGraphInfo).ItemSelectedEvent += QuoteDiagramControl_ItemSelectedEvent; (diagram.Info as IGraphInfo).ItemUnSelectedEvent += QuoteDiagramControl_ItemUnSelectedEvent; (diagram.Info as IGraphInfo).AnnotationChanged += QuoteDiagramControl_AnnotationChanged; diagram.Constraints = GraphConstraints.Default | (GraphConstraints.Undoable & ~GraphConstraints.DrawingTool); (diagram.Info as IGraphInfo).Commands.Zoom.Execute(new ZoomPositionParameter { ZoomCommand = ZoomCommand.Zoom, ZoomTo = 1 }); } private void QuoteDiagramControl_AnnotationChanged(object sender, ChangeEventArgs args) { CheckScalers(); SaveDiagram(); } private double GetDiagramScale() { double result = 100.0F; var scaler = (diagram.Nodes as NodeCollection).OfType().FirstOrDefault(); if (scaler != null) { var pixelwidth = scaler.UnitWidth; var sText = (scaler.Annotations as AnnotationCollection).FirstOrDefault()?.Content as string; if (double.TryParse(sText, out var measured)) result = Math.Round(measured / (scaler.UnitWidth * 10.0F)); } return result; } private void CheckScalers() { ScaleBox.Text = string.Format("1:{0:F2}", GetDiagramScale()); ScaleButton.IsEnabled = !(diagram.Nodes as NodeCollection).OfType().Any(); } private void ScaleButton_Click(object sender, RoutedEventArgs e) { var scaler = QuoteDiagramSymbolCache.CreateScaler(); scaler.OffsetX = 100; scaler.OffsetY = 100; (diagram.Nodes as NodeCollection).Add(scaler); CheckScalers(); } private void QuoteDiagramControl_ItemUnSelectedEvent(object sender, DiagramEventArgs args) { Logger.Send(LogType.Information, "", "ItemUnSelected"); CheckScalers(); } private void QuoteDiagramControl_ItemSelectedEvent(object sender, DiagramEventArgs args) { Logger.Send(LogType.Information, "", "ItemSelected"); CheckScalers(); } private void QuoteDiagramControl_ConnectorTargetChangedEvent(object sender, ChangeEventArgs args) { Logger.Send(LogType.Information, "", "ConnectorTargetChanged"); CheckScalers(); } private void QuoteDiagramControl_ConnectorSourceChangedEvent(object sender, ChangeEventArgs args) { Logger.Send(LogType.Information, "", "ConnectorSourceChanged"); CheckScalers(); } private void ItemAddedEvent(object sender, ItemAddedEventArgs args) { try { _disablesave = true; var node = args.Item as NodeViewModel; if (node != null) { if (node is QuoteDiagramScalerModel) { node.ContentTemplate = QuoteDiagramSymbolCache.Scalers.FirstOrDefault()?.ContentTemplate; } else { node.Key = (args.OriginalSource as NodeViewModel).ID; node.Content = (args.OriginalSource as NodeViewModel).Content; node.ContentTemplate = (args.OriginalSource as NodeViewModel).ContentTemplate; } // LoadSymbolContent(node, x => String.Equals((args.OriginalSource as NodeViewModel).ID.ToString(), x.ID)); node.UnitHeight = node.UnitHeight * LengthUnit.Centimeters / 10.0F; // / double.Parse(ScaleBox.Text); node.UnitWidth = node.UnitWidth * LengthUnit.Centimeters / 10.0F; // / double.Parse(ScaleBox.Text); } else { var conn = args.Item as QuoteDiagramConnectorModel; if (conn != null) LoadConnectorContent(conn, (args.OriginalSource as ConnectorViewModel)?.ID?.ToString()); } } finally { _disablesave = false; } } private void Diagram_HistoryChangedEvent(object sender, HistoryChangedEventArgs args) { Logger.Send(LogType.Information, "", string.Format("HistoryChanged {0}", args.Item.Mode)); CheckScalers(); SaveDiagram(); } private void Diagram_ItemTappedEvent(object sender, DiagramEventArgs args) { if (args.Item is IConnector) { //Getting the mouse point while tap on the connector var pp = ((args as ItemTappedEventArgs).MouseEventArgs as MouseEventArgs).GetPosition(diagram.Page); //Specify the editing point, editing type and hit padding value var addremoveargs = new AddRemoveStraightSegmentArgs { Point = pp, SegmentEditing = SegmentEditing.Add, HitPadding = 5 }; //Method to add or remove the segment ((args.Item as IConnector).Info as IConnectorInfo).EditSegment(addremoveargs); } } private void Select_Click(object sender, RoutedEventArgs e) { if (Diagram == null) return; } private void TakeOff_Click(object sender, RoutedEventArgs e) { using (new WaitCursor()) { var scale = GetDiagramScale(); var updates = new List(); var takeoffs = new Client().Query(new Filter(x => x.Diagram.ID).IsEqualTo(Diagram.ID)); var nodes = diagram.Nodes as NodeCollection; foreach (var area in nodes.Where(x => x is QuoteDiagramAreaModel)) { QuoteTakeoff update = null; var id = (Guid)CoreUtils.GetPropertyValue(area.Info, "InternalID"); var row = takeoffs.Rows.FirstOrDefault(r => Equals(r.Get(x => x.DiagramObject), id)); if (row != null) { update = row.ToObject(); takeoffs.Rows.Remove(row); } else { update = new QuoteTakeoff(); update.Quote.ID = Diagram.Quote.ID; update.Diagram.ID = Diagram.ID; update.DiagramObject = id.ToString(); } update.Description = (area.Annotations as AnnotationCollection).FirstOrDefault()?.Content?.ToString(); update.Dimensions.Set( new QuoteTakeOffUnit() { HasLength = true, HasWidth = true, Formula = "[x] * [y]", Format = "[x] * [y]" }, 0F, Math.Round(area.UnitHeight * scale * 10.0F), Math.Round(area.UnitWidth * scale * 10.0F), 0F, 0F ); updates.Add(update); } if (updates.Any()) new Client().Save(updates, ""); updates.Clear(); foreach (var row in takeoffs.Rows) updates.Add(new QuoteTakeoff { ID = row.Get(x => x.ID) }); if (updates.Any()) new Client().Delete(updates, ""); } MessageBox.Show("Done"); } private void Zoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (diagram == null) return; var graphinfo = diagram.Info as IGraphInfo; graphinfo.Commands.Zoom.Execute(new ZoomPositionParameter { ZoomCommand = ZoomCommand.Zoom, ZoomTo = e.NewValue / 100 }); Logger.Send(LogType.Information, "", string.Format("Zoomed to {0:F4}", e.NewValue / 100)); } private void EditStencil_Click(object sender, RoutedEventArgs e) { var stencil = (Stencils.SelectedItem as DynamicTabItem).Content as Stencil; var list = stencil == areas ? new MasterList(typeof(QuoteDiagramArea)) : stencil == symbols ? new MasterList(typeof(QuoteDiagramSymbol)) : new MasterList(typeof(QuoteDiagramConnector)); if (list.ShowDialog() == true) { QuoteDiagramSymbolCache.Refresh(); areas.SymbolSource = QuoteDiagramSymbolCache.Areas; symbols.SymbolSource = QuoteDiagramSymbolCache.Symbols; connectors.SymbolSource = QuoteDiagramSymbolCache.Connectors; } } #region CustomSave //private String PointToString(Point? point) //{ // return String.Format("{0},{1}", point.HasValue ? point.Value.X.ToString() : "", point.HasValue ? point.Value.Y.ToString() : ""); //} //private Point? StringToPoint(String x, String y) //{ // if (!String.IsNullOrWhiteSpace(x) && !String.IsNullOrWhiteSpace(y)) // return new Point(double.Parse(x), double.Parse(y)); // return null; //} //private String VectorToString(Vector? vector) //{ // return String.Format("{0},{1}", vector.HasValue ? vector.Value.X.ToString() : "", vector.HasValue ? vector.Value.Y.ToString() : ""); //} //private Vector? StringToVector(String x, String y) //{ // if (!String.IsNullOrWhiteSpace(x) && !String.IsNullOrWhiteSpace(y)) // return new Vector(double.Parse(x), double.Parse(y)); // return null; //} //private String StraightSegmentToString(StraightSegment segment) //{ // String result = String.Format("S,{0}",PointToString(segment.Point)); // return result; //} //private StraightSegment StringToStraightSegment(String segment) //{ // String[] comps = segment.Split(','); // StraightSegment result = new StraightSegment(); // result.Point = StringToPoint(comps[1], comps[2]); // return result; //} //private String OrthogonalSegmentToString(OrthogonalSegment segment) //{ // String result = String.Format("O,{0},{1},{2},{3}", // segment.Length.Min<= double.MinValue ? "" :segment.Length.Min.ToString(), // segment.Length.Max >= double.MaxValue ? "" : segment.Length.Max.ToString(), // double.IsNaN(segment.Length.Value) ? "" : segment.Length.Value.ToString(), // segment.Direction.ToString()); // return result; //} //private OrthogonalSegment StringToOrthogonalSegment(String segment) //{ // String[] comps = segment.Split(','); // OrthogonalSegment result = new OrthogonalSegment(); // try // { // result.Length = new DoubleExt( // String.IsNullOrWhiteSpace(comps[1]) ? double.MinValue : double.Parse(comps[1]), // String.IsNullOrWhiteSpace(comps[2]) ? double.MaxValue : double.Parse(comps[2]), // String.IsNullOrWhiteSpace(comps[2]) ? double.NaN : double.Parse(comps[3]) // ); // } // catch (Exception e) // { // result.Length = new DoubleExt(); // } // result.Direction = (OrthogonalDirection)Enum.Parse(typeof(OrthogonalDirection), comps[4]); // return result; //} //private String CubicSegmentToString(CubicCurveSegment segment) //{ // String result = String.Format("C,{0},{1},{2},{3},{4}", // PointToString(segment.Point1), // PointToString(segment.Point2), // PointToString(segment.Point3), // VectorToString(segment.Vector1), // VectorToString(segment.Vector2) // ); // return result; //} //private CubicCurveSegment StringToCubicSegment(String segment) //{ // String[] comps = segment.Split(','); // CubicCurveSegment result = new CubicCurveSegment(); // result.Point1 = StringToPoint(comps[1], comps[2]); // result.Point2 = StringToPoint(comps[3], comps[4]); // result.Point3 = StringToPoint(comps[5], comps[6]); // result.Vector1 = StringToVector(comps[7], comps[8]); // result.Vector2 = StringToVector(comps[9], comps[10]); // return result; //} //private String QuadraticSegmentToString(QuadraticCurveSegment segment) //{ // String result = String.Format("Q,{0},{1}", // PointToString(segment.Point1), // PointToString(segment.Point2) // ); // return result; //} //private QuadraticCurveSegment StringToQuadraticSegment(String segment) //{ // String[] comps = segment.Split(','); // QuadraticCurveSegment result = new QuadraticCurveSegment(); // result.Point1 = StringToPoint(comps[1], comps[2]); // result.Point2 = StringToPoint(comps[3], comps[4]); // return result; //} //private String SegmentToString(IConnectorSegment segment) //{ // if (segment is StraightSegment) // return StraightSegmentToString(segment as StraightSegment); // if (segment is OrthogonalSegment) // return OrthogonalSegmentToString(segment as OrthogonalSegment); // if (segment is CubicCurveSegment) // return CubicSegmentToString(segment as CubicCurveSegment); // if (segment is QuadraticCurveSegment) // return QuadraticSegmentToString(segment as QuadraticCurveSegment); // throw new Exception(segment.GetType().ToString()); //} //private IConnectorSegment StringToSegment(String segment) //{ // if (segment.StartsWith("S")) // return StringToStraightSegment(segment); // else if (segment.StartsWith("O")) // return StringToOrthogonalSegment(segment); // else if (segment.StartsWith("C")) // return StringToCubicSegment(segment); // else if (segment.StartsWith("Q")) // return StringToQuadraticSegment(segment); // throw new Exception(segment); //} //private ObservableCollection StringToSegments(String data) //{ // ObservableCollection result = new ObservableCollection(); // String[] segments = data.Split(';'); // foreach (var segment in segments) // result.Add(StringToSegment(segment)); // return result; //} //private void CustomSaveDiagram() //{ // List data = new List(); // NodeCollection nodes = diagram.Nodes as NodeCollection; // foreach (var node in nodes) // data.Add(String.Format("N {0} {1} {2} {3} {4} {5} {6} {7}", node.ID, node.Key, node.Name, node.OffsetX, node.OffsetY, node.UnitWidth, node.UnitHeight, node.RotateAngle)); // ConnectorCollection connectors = diagram.Connectors as ConnectorCollection; // foreach (var connector in connectors) // { // List encoded = new List(); // var segments = connector.Segments as ObservableCollection; // foreach (var segment in segments) // encoded.Add(SegmentToString(segment)); // data.Add(String.Format("C {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}", // connector.ID, // connector.Key, // connector.Name, // connector.SourcePoint.X, // connector.SourcePoint.Y, // connector.SourceNode != null ? (connector.SourceNode as NodeViewModel).ID : "", // connector.TargetPoint.X, // connector.TargetPoint.Y, // connector.TargetNode != null ? (connector.TargetNode as NodeViewModel).ID : "", // String.Join(";", encoded)) // ); // } // Diagram.Data = String.Join("\n", data); // new Client().Save(Diagram, "", (d, err) => { }); //} //private void DoCustomLoadDiagram() //{ // ConnectorCollection connectors = diagram.Connectors as ConnectorCollection; // connectors.Clear(); // NodeCollection nodes = diagram.Nodes as NodeCollection; // nodes.Clear(); // if ((Diagram != null) && (!String.IsNullOrWhiteSpace(Diagram.Data))) // { // String[] lines = Diagram.Data.Split('\n'); // foreach (var line in lines.Where(x => x.StartsWith("N "))) // { // String[] comps = line.Split(' '); // if (comps.Length == 9) // { // NodeViewModel node = new NodeViewModel(); // node.ID = comps[1]; // node.Key = comps[2]; // node.Name = comps[3]; // node.OffsetX = double.Parse(comps[4]); // node.OffsetY = double.Parse(comps[5]); // node.UnitWidth = double.Parse(comps[6]); // node.UnitHeight = double.Parse(comps[7]); // node.RotateAngle = double.Parse(comps[8]); // LoadSymbolContent(node); // nodes.Add(node); // } // } // foreach (var line in lines.Where(x => x.StartsWith("C "))) // { // String[] comps = line.Split(' '); // if (comps.Length == 11) // { // ConnectorViewModel conn = new ConnectorViewModel(); // conn.ID = comps[1]; // conn.Key = comps[2]; // conn.Name = comps[3]; // conn.SourcePoint = StringToPoint(comps[4], comps[5]).Value; // conn.SourceNode = nodes.FirstOrDefault(x => String.Equals(x.ID, comps[6])); // conn.TargetPoint = StringToPoint(comps[7], comps[8]).Value; // conn.TargetNode = nodes.FirstOrDefault(x => String.Equals(x.ID, comps[9])); // conn.Segments = StringToSegments(comps[10]); // LoadConnectorContent(conn); // connectors.Add(conn); // } // } // } //} #endregion } }