/// <summary> /// Delegate called when the control is initialized. /// </summary> /// <param name="pEventArgs">The event arguments.</param> protected override void OnInitialized(EventArgs pEventArgs) { PortViewModel lPortViewModel = this.DataContext as PortViewModel; if (lPortViewModel == null) { return; } PortContainer lParentContainer = this.FindVisualParent <PortContainer>(); if (lParentContainer == null) { return; } PortView lPortView = lParentContainer.GetContainerForViewModel(lPortViewModel); if (lPortView != null) { AdornerLayeredCanvas lCanvas = this.FindVisualParent <AdornerLayeredCanvas>(); if (lCanvas != null) { // Creating the adorner layer. AdornerLayer lLayer = lCanvas.AdornerLayer; // Creating the adorner and propagating this control background. this.mAdorner = new ConnectorAdorner(lPortView); this.UpdateConnectorsBackground(); // Adding the adorner to the layer. lLayer.Add(this.mAdorner); } } }
/// <summary> /// Arranges the port views by taking in account the computed size of the panel viewport. /// </summary> /// <param name="pFinalSize">The available size.</param> /// <returns>The size used (here equals to the available size).</returns> protected override Size ArrangeOverride(Size pFinalSize) { // (1) Calling this base method is the key for the width of each port view to be well computed !!! base.ArrangeOverride(pFinalSize); int lInputPortsIndex = 0; int lOutputPortsIndex = 0; if (this.InternalChildren.Count > 0) { // Using the ActualWidth computed by the base arrange (1) method to have the good column width. double lInputPortsWidth = -1; PortView[] lInputPorts = this.InternalChildren.Cast <PortView>().Where(pPort => pPort.Direction == PortDirection.Input).ToArray(); if (lInputPorts.Any()) { lInputPortsWidth = Math.Round(lInputPorts.Max(pPort => pPort.ActualWidth) - this.LineWidth / 2.0); } double lOutputPortsWidth = -1; PortView[] lOutputPorts = this.InternalChildren.Cast <PortView>().Where(pPort => pPort.Direction == PortDirection.Output).ToArray(); if (lOutputPorts.Any()) { lOutputPortsWidth = Math.Round(lOutputPorts.Max(pPort => pPort.ActualWidth) - this.LineWidth / 2.0); } if (lInputPortsWidth == -1 && lOutputPortsWidth != -1) { lInputPortsWidth = lOutputPortsWidth; } if (lInputPortsWidth != -1 && lOutputPortsWidth == -1) { lOutputPortsWidth = lInputPortsWidth; } for (int i = 0, lCount = this.InternalChildren.Count; i < lCount; ++i) { PortView lPort = this.InternalChildren[i] as PortView; if (lPort != null) { if (lPort.Direction == PortDirection.Input) { // Input ports are in the first column. lPort.Arrange(new Rect(0.0, lInputPortsIndex * (lPort.DesiredSize.Height + this.LineWidth), lInputPortsWidth, lPort.DesiredSize.Height)); lInputPortsIndex++; } else { // Output ports are in the second column. lPort.Arrange(new Rect(lInputPortsWidth + this.LineWidth, lOutputPortsIndex * (lPort.DesiredSize.Height + this.LineWidth), lOutputPortsWidth, lPort.DesiredSize.Height)); lOutputPortsIndex++; } } } } return(pFinalSize); }
/// <summary> /// Innitializes a new instance of the <see cref="ConnectorsAdorner"/> class. /// </summary> /// <param name="pAdornedElement">The orned prot view.</param> public ConnectorsAdorner(PortView pAdornedElement) : base(pAdornedElement) { // Creating the connectors contained in the adorner. this.mVisualChildren = new VisualCollection(this); this.mVisualChildren.Add(new InputConnector(pAdornedElement)); this.mVisualChildren.Add(new OutputConnector(pAdornedElement)); // Ensuring the measure is well computed. this.AdornedPortView.SizeChanged += new SizeChangedEventHandler(this.OnPortViewSizeChanged); }
/// <summary> /// Prespares the container for the given item. /// </summary> /// <param name="pElement">The item container.</param> /// <param name="pItem">The contained item.</param> protected override void PrepareContainerForItemOverride(DependencyObject pElement, object pItem) { base.PrepareContainerForItemOverride(pElement, pItem); PortView lContainer = pElement as PortView; if (lContainer != null) { // Updating the background. lContainer.Background = this.Background; } }
/// <summary> /// Updates the items background brush by applying the background of this container. /// </summary> private void UpdateItemsBackground() { if (this.ItemsSource != null) { foreach (PortViewModel lItem in this.ItemsSource) { PortView lPortView = this.ItemContainerGenerator.ContainerFromItem(lItem) as PortView; if (lPortView != null) { lPortView.Background = this.Background; } } } }
/// <summary> /// Delegate called when the control is initialized. /// </summary> /// <param name="pEventArgs">The event arguments.</param> protected override void OnInitialized(EventArgs pEventArgs) { // The adorned port view is given to the control by the DataContext property. PortView lPortView = this.DataContext as PortView; if (lPortView != null) { AdornerLayeredCanvas lCanvas = this.FindVisualParent <AdornerLayeredCanvas>(); if (lCanvas != null) { // Creating the adorner layer. AdornerLayer lLayer = lCanvas.AdornerLayer; // Creating the adorner and propagating this control background. this.Adorner = new ConnectorsAdorner(lPortView); this.UpdateConnectorsBackground(); // Adding the adorner to the layer. lLayer.Add(this.Adorner); } } }
/// <summary> /// Initializes a new instance of the <see cref="OutputConnector"/> class. /// </summary> /// <param name="pParentPort">The connector parent port.</param> public OutputConnector(PortView pParentPort) : base(pParentPort) { }
/// <summary> /// Method called when the control content changed. /// </summary> /// <param name="pOldContent">The previous content.</param> /// <param name="pNewContent">The new content.</param> protected override void OnContentChanged(object pOldContent, object pNewContent) { // Calling ancestor methods. base.OnContentChanged(pOldContent, pNewContent); BindingOperations.ClearAllBindings(this); // The content is the view model. ConnectionViewModel lViewModel = pNewContent as ConnectionViewModel; if (lViewModel == null) { // Unreferencing the connectors to avoid memory leaks. this.OutputConnector.ConnectionsCount--; this.InputConnector.ConnectionsCount--; this.OutputConnector.PositionChanged -= this.OnConnectorPositionChanged; this.InputConnector.PositionChanged -= this.OnConnectorPositionChanged; this.OutputConnector = null; this.InputConnector = null; } else { // Binding the Background property. Binding lBackgroundBinding = new Binding("Brush"); lBackgroundBinding.Source = lViewModel; lBackgroundBinding.Mode = BindingMode.OneWay; this.SetBinding(Connection.BackgroundProperty, lBackgroundBinding); // Filling the output and input connectors. SimpleGraphView lParentCanvas = this.FindVisualParent <SimpleGraphView>(); if (lViewModel != null && lParentCanvas != null) { NodeView lOutputNode = lParentCanvas.GetContainerForViewModel <NodeViewModel, NodeView>(lViewModel.Output.ParentNode); if (lOutputNode != null) { PortView lOutputPort = lOutputNode.GetContainerForPortViewModel(lViewModel.Output); if (lOutputPort != null) { this.OutputConnector = lOutputPort.Connector as OutputConnector; if (this.OutputConnector != null) { this.OutputConnector.PositionChanged += this.OnConnectorPositionChanged; this.OutputConnector.ConnectionsCount++; } } } NodeView lInputNode = lParentCanvas.GetContainerForViewModel <NodeViewModel, NodeView>(lViewModel.Input.ParentNode); if (lInputNode != null) { PortView lInputPort = lInputNode.GetContainerForPortViewModel(lViewModel.Input); if (lInputPort != null) { this.InputConnector = lInputPort.Connector as InputConnector; if (this.InputConnector != null) { this.InputConnector.PositionChanged += this.OnConnectorPositionChanged; this.InputConnector.ConnectionsCount++; } } } } } this.UpdateRendering(); }
/// <summary> /// Computes the size of the panel viewport. /// </summary> /// <param name="pAvailableSize">The initial available size.</param> /// <returns>The viewport desired size.</returns> protected override Size MeasureOverride(Size pAvailableSize) { Size lColumnSize = base.MeasureOverride(pAvailableSize); Size lInputPortsSize = new Size(); Size lOutputPortsSize = new Size(); int lInputPortsIndex = 0; int lOutputPortsIndex = 0; int lInputPortsCount = this.InternalChildren.Cast <PortView>().Where(lPort => lPort.Direction == PortDirection.Input).Count(); int lOutputPortsCount = this.InternalChildren.Cast <PortView>().Where(lPort => lPort.Direction == PortDirection.Output).Count(); // Width is the column width. lInputPortsSize.Width = lColumnSize.Width + this.LineWidth / 2.0; lOutputPortsSize.Width = lColumnSize.Width + this.LineWidth / 2.0; // Iterating threw the ports to compute the height. for (int i = 0, lCount = this.InternalChildren.Count; i < lCount; ++i) { PortView lPort = this.InternalChildren[i] as PortView; if (lPort != null) { lPort.Measure(pAvailableSize); if (lPort.Direction == PortDirection.Input) { if (lInputPortsIndex == 0 || lInputPortsIndex == lInputPortsCount - 1) { lInputPortsSize.Height += lPort.DesiredSize.Height + this.LineWidth / 2.0; } else { lInputPortsSize.Height += lPort.DesiredSize.Height + this.LineWidth; } lInputPortsIndex++; } else { if (lOutputPortsIndex == 0 || lOutputPortsIndex == lOutputPortsCount - 1) { lOutputPortsSize.Height += lPort.DesiredSize.Height + this.LineWidth / 2.0; } else { lOutputPortsSize.Height += lPort.DesiredSize.Height + this.LineWidth; } lOutputPortsIndex++; } } } // Computing the size of the panel. Size lAvailableSize = new Size { Height = Math.Max(lInputPortsSize.Height, lOutputPortsSize.Height), Width = lInputPortsSize.Width + lOutputPortsSize.Width }; // This is the minimum size the control must have. return(lAvailableSize); }
/// <summary> /// Initializes a new instance of the <see cref="AConnector"/> class. /// </summary> /// <param name="pParentPort">The connector parent port.</param> protected AConnector(PortView pParentPort) { this.ParentPort = pParentPort; this.LayoutUpdated += this.OnLayoutUpdated; }