public void MouseMove(object sender, MouseEventArgs e) { // If the canvas reference is null then we ignore mouse events if (null == m_canvas) { return; } Point mousePt = e.GetPosition(m_canvas); // Clear the border if we'd previously set one if (null != m_puWithAlteredBorderColor) { m_puWithAlteredBorderColor.SetBorderColor(ProcessUnitBorderColor.NoBorder); m_puWithAlteredBorderColor = null; } // See if we're hovering over a process unit (will be null if we're not) m_puWithAlteredBorderColor = m_canvas.GetChildAt(e.GetPosition(m_canvas), m_sourcePlacementIcon) as ProcessUnitControl; // Set the location of icon so that it's right under the mouse pointer m_sourcePlacementIcon.SetValue(Canvas.LeftProperty, mousePt.X - m_sourcePlacementIcon.ActualWidth / 2.0); m_sourcePlacementIcon.SetValue(Canvas.TopProperty, mousePt.Y - m_sourcePlacementIcon.ActualHeight / 2.0); // If we're over a process unit then we need to set its border if (null != m_puWithAlteredBorderColor) { m_puWithAlteredBorderColor.SetBorderColor( m_puWithAlteredBorderColor.ProcessUnit.CanAcceptOutgoingStream(m_stream) ? ProcessUnitBorderColor.AcceptingStreams : ProcessUnitBorderColor.NotAcceptingStreams); } }
/// <summary> /// The member variable m_highlightedHover can be a reference to a process unit with a highlighted /// border or a stream with a specially colored stem line. This method removes either of these /// highlights and sets the member variable back to null. /// </summary> private void UnhighlightHover() { if (null == m_highlightedHover) { return; } ProcessUnitControl gpu = m_highlightedHover as ProcessUnitControl; if (null != gpu) { gpu.SetBorderColor(ProcessUnitBorderColor.NoBorder); } else { PFD.Streams.StreamControl s = m_highlightedHover as PFD.Streams.StreamControl; if (null != s) { s.Selected = true; s.Selected = false; } } m_highlightedHover = null; }
public void MouseMove(object sender, MouseEventArgs e) { if (null == m_placementIcon) { return; } // Set the location of the icon to follow the mouse Point p = e.GetPosition(m_canvas); m_placementIcon.SetValue(Canvas.LeftProperty, p.X - m_placementIcon.Width / 2.0); m_placementIcon.SetValue(Canvas.TopProperty, p.Y - m_placementIcon.Height / 2.0); // If we've highlighted a process unit or stream then clear the highlight UnhighlightHover(); // See if we're hovering over a process unit (will be null if we're not) m_highlightedHover = m_canvas.GetChildAtIncludeStreams(p, m_placementIcon); ProcessUnitControl pu = m_highlightedHover as ProcessUnitControl; ChemProV.PFD.Streams.StreamControl stream = m_highlightedHover as ChemProV.PFD.Streams.StreamControl; // Set the border if we are hovering over a process unit to indicate that we can attach // an anchored comment to it if (null != pu) { pu.SetBorderColor(ProcessUnitBorderColor.AcceptingStreams); } else if (null != stream) { stream.SetLineBrush(new SolidColorBrush(Colors.Green)); } }
public PlacingNewProcessUnit(ControlPalette sender, DrawingCanvas canvas, Type processUnitType) { m_canvas = canvas; m_palette = sender; m_type = processUnitType; m_workspace = canvas.GetWorkspace(); SolidColorBrush whiteBrush = new SolidColorBrush(Colors.White); // Create the placement icon. This will hover under the mouse pointer // as it moves and a mouse-down event will complete the placement. BitmapImage bmp = new BitmapImage(); bmp.UriSource = new Uri(ProcessUnitControl.GetIconSource(processUnitType), UriKind.Relative); Image img = new Image() { Source = bmp, Width = 44.0, Height = 44.0 }; m_placementIcon = new Border(); m_placementIcon.Background = whiteBrush; m_placementIcon.Child = img; m_placementIcon.BorderThickness = new Thickness(0.0); // Add it to the canvas but don't show it until we get our first mouse-move event canvas.AddNewChild(m_placementIcon); m_placementIcon.Visibility = Visibility.Collapsed; // Deselect canvas.SelectedElement = null; }
// Refactoring on this method is done (logic-wise, could use some cleanup otherwise) private static void DeleteHEWU(ProcessUnitControl he, DrawingCanvas canvas) { Workspace ws = canvas.GetWorkspace(); // Heat exchangers with utilities must also delete the heat stream that's incoming // Normally the heat stream is at index 0 among the incoming streams, but it seems like // this does not always hold true when loading from files so it's just safer to search // for it HeatStream heatStream = null; foreach (AbstractStream incomingStream in he.ProcessUnit.IncomingStreams) { if (incomingStream is HeatStream) { heatStream = incomingStream as HeatStream; break; } } PFD.Streams.StreamControl heatStreamControl = canvas.GetStreamControl(heatStream) as PFD.Streams.StreamControl; List <IUndoRedoAction> undos = new List <IUndoRedoAction>(); undos.Add(new Logic.Undos.AddToWorkspace(heatStream)); undos.Add(new Logic.Undos.AddToWorkspace(he.ProcessUnit)); // We need to check if the attached stream has a source if (null != heatStream.Source) { // Detach with undo undos.Add(new Logic.Undos.AttachOutgoingStream(heatStream.Source, heatStream)); heatStream.Source.DetachOutgoingStream(heatStream); } // Detach all outgoing streams and make undos foreach (AbstractStream s in he.ProcessUnit.OutgoingStreams) { undos.Add(new Logic.Undos.SetStreamSource(s, he.ProcessUnit, null, s.SourceLocation)); s.Source = null; } // Detach all incoming streams and make undos foreach (AbstractStream s in he.ProcessUnit.IncomingStreams) { undos.Add(new Logic.Undos.SetStreamDestination(s, he.ProcessUnit, null, s.DestinationLocation)); s.Destination = null; } ws.AddUndo(new UndoRedoCollection( "Undo deletion of heat exchanger with utility", undos.ToArray())); // Remove the stream and process unit from the workspace. Event handlers will update the UI. ws.RemoveStream(heatStream); ws.RemoveProcessUnit(he.ProcessUnit); }
public void MouseMove(object sender, MouseEventArgs e) { if (!m_mouseDown) { return; } // We can't do anything if the canvas is read-only if (m_canvas.IsReadOnly) { return; } Point pt = e.GetPosition(m_canvas); MathCore.Vector diff = (new MathCore.Vector(pt.X, pt.Y)) - m_mouseDownPt; diff = (m_originalLocation + diff); pt = new Point(diff.X, diff.Y); // If we changed a border color, change it back and null the reference if (null != m_puThatGotBorderChange) { m_puThatGotBorderChange.SetBorderColor(ProcessUnitBorderColor.Selected); m_puThatGotBorderChange = null; } // Various objects have slightly different moving rules so we need to check the type ProcessUnitControl lpu = m_object as ProcessUnitControl; if (null != lpu) { // First off, move the process unit lpu.ProcessUnit.Location = new MathCore.Vector(pt.X, pt.Y); // See if we're dragging it over anything else object hoveringOver = m_canvas.GetChildAt(pt, lpu); // See if it's a stream connection endpoint DraggableStreamEndpoint endpoint = hoveringOver as DraggableStreamEndpoint; if (null != endpoint) { m_puThatGotBorderChange = lpu; // Set the process unit's border color m_puThatGotBorderChange.SetBorderColor(endpoint.CanConnectTo(lpu) ? ProcessUnitBorderColor.AcceptingStreams : ProcessUnitBorderColor.NotAcceptingStreams); } } else { // Other items just get their locations set m_object.Location = pt; } // NOTE: Stream-oriented moving stuff is handled elsewhere. See the MovingStreamEndpoint class }
/// <summary> /// This returns the rule that needs to be checked for the GenericProcessUnit /// Currently it returns the ReactorProcessUnitRule if pu is a reactor otherwise /// it returns the GenericProcessUnitRule /// </summary> /// <param name="pu">The process unit that will be checked with the rule returned</param> /// <returns>GenericProcessUnitRule which could be a ReactorProcessUnitRule since it inherients from GenericProcessUnitRule</returns> public static GenericProcessUnitRule GetProcessUnitRule(ProcessUnitControl pu) { GenericProcessUnitRule puRule; if (pu.ProcessUnit is Reactor) { puRule = new ReactorProcessUnitRule(); } else if (pu.ProcessUnit is HeatExchangerNoUtility) { puRule = new HeatExchangerWithoutUtilityProcessUnitRule(); } else { puRule = new GenericProcessUnitRule(); } return(puRule); }
private static void DeleteProcessUnitWithUndo(ProcessUnitControl pu, Workspace ws) { // Initialize the list of undos List <IUndoRedoAction> undos = new List <IUndoRedoAction>(); undos.Add(new ChemProV.Logic.Undos.AddToWorkspace(pu.ProcessUnit)); // Deleting a process unit could potentially affect equations because equations can reference // a process unit as their scope. Therefore we need to check all equations if they have this // process unit set as their scope and change w/ undo if they do. foreach (EquationModel em in ws.Equations) { if (em.Scope.Classification == EquationScopeClassification.SingleUnit && em.Scope.Name == pu.ProcessUnit.Label) { undos.Add(new Logic.Undos.SetProperty(em, "Scope", em.Scope)); em.Scope = new EquationScope(EquationScopeClassification.Overall, "Overall"); } } // Detach all incoming streams and make undos foreach (AbstractStream s in pu.ProcessUnit.IncomingStreams) { undos.Add(new SetStreamDestination(s, pu.ProcessUnit, null, s.DestinationLocation)); s.Destination = null; } // Detach all outgoing streams and make undos foreach (AbstractStream s in pu.ProcessUnit.OutgoingStreams) { undos.Add(new SetStreamSource(s, pu.ProcessUnit, null, s.SourceLocation)); s.Source = null; } // Remove the process unit from the workspace. Event handlers will update UI. ws.RemoveProcessUnit(pu.ProcessUnit); // Finalize the undo ws.AddUndo(new UndoRedoCollection("Undo deletion of process unit", undos.ToArray())); }
/// <summary> /// Determines whether or not this endpoint can connect to the specified process unit control /// </summary> public bool CanConnectTo(ProcessUnitControl processUnit) { return(CanConnectTo(processUnit.ProcessUnit)); }
private void DropProcessUnit(ProcessUnitControl pu, Point location) { // We want to see if the process unit is being dragged and dropped onto a stream // source or destination // Get the element (besides the one being dragged) that's at the mouse location object dropTarget = m_canvas.GetChildAt(location, m_object); // If there is no child at that point or there is a child but it's not a stream endpoint // then this ends up just being a move of the process unit if (null == dropTarget || !(m_canvas.IsStreamEndpoint(dropTarget as UIElement))) { // Add an undo that will move the process unit back to where it was m_workspace.AddUndo(new UndoRedoCollection("Undo moving process unit", new Logic.Undos.SetProcessUnitLocation(pu.ProcessUnit, m_originalLocation))); // The control is already in the right position from the mouse-move event, so we're done return; } // Coming here means that we've dropped the process unit on a stream endpoint. We need to // check if this is a valid move or not and handle it appropriately. DraggableStreamEndpoint streamEndpoint = dropTarget as DraggableStreamEndpoint; if (streamEndpoint.CanConnectTo(pu)) { AbstractStream stream = streamEndpoint.ParentStream.Stream; switch (streamEndpoint.Type) { case DraggableStreamEndpoint.EndpointType.StreamDestination: m_workspace.AddUndo(new UndoRedoCollection("Undo moving and connecting process unit", new Logic.Undos.DetachIncomingStream(pu.ProcessUnit, streamEndpoint.ParentStream.Stream), new Logic.Undos.SetStreamDestination(stream, null, pu.ProcessUnit, m_originalLocation))); pu.ProcessUnit.AttachIncomingStream(streamEndpoint.ParentStream.Stream); stream.Destination = pu.ProcessUnit; break; case DraggableStreamEndpoint.EndpointType.StreamSource: m_workspace.AddUndo(new UndoRedoCollection("Undo moving and connecting process unit", new DetachOutgoingStream(pu.ProcessUnit, streamEndpoint.ParentStream.Stream), new SetStreamSource(stream, null, pu.ProcessUnit, new MathCore.Vector(streamEndpoint.Location.X, streamEndpoint.Location.Y)))); pu.ProcessUnit.AttachOutgoingStream(stream); stream.Source = pu.ProcessUnit; break; default: // Um.... break; } } else // Not a valid move { // In this case we simply snap it back to where it was when the move started. // Ideally we should have some sort of animation that makes it slide back to its original // location, but that can come much later if we want it. pu.Location = new Point(m_originalLocation.X, m_originalLocation.Y); // Note that in either case we've essentially canceled the action and no net-change has // been made. Thus we don't need to create an undo. return; } }
/// <summary> /// Adds menu options for the subprocess color changing /// </summary> private void AddSubprocessMenuOptions(ContextMenu newContextMenu, ProcessUnitControl pu) { MenuItem parentMenuItem = new MenuItem(); parentMenuItem.Header = "Subprocess"; newContextMenu.Items.Add(parentMenuItem); // We're using this item as a label, so don't let the user click it parentMenuItem.IsHitTestVisible = false; // Change the colors to signal to the user that it's a label parentMenuItem.Background = new SolidColorBrush(Colors.LightGray); parentMenuItem.Foreground = new SolidColorBrush(Color.FromArgb(255, 100, 100, 100)); parentMenuItem.FontWeight = FontWeights.Bold; if (false) { // Create a submenu for colors. See the declaration of the Core.NamedColors.All array for // the list of colors that are being used. Make changes in that array (not in this code) // to change the list of available colors. foreach (Core.NamedColor nc in Core.NamedColors.All) { MenuItem menuItem = new MenuItem(); menuItem.Header = nc.Name; menuItem.Tag = System.Tuple.Create <ProcessUnitControl, Color>( pu, nc.Color); // Show the menu item with a check next to it if it's the current color if (nc.Color.Equals(pu.Subprocess)) { menuItem.Icon = Core.App.CreateImageFromSource("check_16x16.png"); } // Add it to the menu newContextMenu.Items.Add(menuItem); // Use an anonymous delegate to handle the click event menuItem.Click += delegate(object sender, RoutedEventArgs e) { // Get the objects we need MenuItem tempMI = sender as MenuItem; System.Tuple <ProcessUnitControl, Color> t = tempMI.Tag as System.Tuple <ProcessUnitControl, Color>; // Create undo item before setting the new subgroup m_workspace.AddUndo(new UndoRedoCollection("Undo subprocess change", new Logic.Undos.SetSubprocess(t.Item1.ProcessUnit))); // Set the subgroup t.Item1.Subprocess = t.Item2; // Make sure to remove the popup menu from the canvas m_canvas.Children.Remove(m_contextMenu); m_contextMenu = null; // Flip back to the default state for the canvas (null) m_canvas.CurrentState = null; }; } } MenuItem mi = new MenuItem(); mi.Header = "Select subprocess..."; mi.Click += delegate(object sender, RoutedEventArgs r) { SubprocessChooserWindow win = new SubprocessChooserWindow( pu as ProcessUnitControl, m_workspace); win.Show(); // Make sure to remove the popup menu from the canvas m_canvas.Children.Remove(m_contextMenu); m_contextMenu = null; // Flip back to the default state for the canvas (null) m_canvas.CurrentState = null; }; newContextMenu.Items.Add(mi); }
private void AddCommentCollectionMenuOptions(ContextMenu newContextMenu, string title) { // Make the header in the menu for the comment-specific options MenuItem menuItem = new MenuItem(); menuItem.Header = title; newContextMenu.Items.Add(menuItem); // We're using this item as a label, so don't let the user click it menuItem.IsHitTestVisible = false; // Change the colors to signal to the user that it's a label menuItem.Background = new SolidColorBrush(Colors.LightGray); menuItem.Foreground = new SolidColorBrush(Color.FromArgb(255, 100, 100, 100)); menuItem.FontWeight = FontWeights.Bold; menuItem = new MenuItem(); menuItem.Header = "Add new comment"; menuItem.Tag = m_canvas.SelectedElement; newContextMenu.Items.Add(menuItem); // Use an anonymous delegate to handle the click event menuItem.Click += delegate(object sender, RoutedEventArgs e) { MenuItem tempMI = sender as MenuItem; PFD.Streams.StreamControl stream = tempMI.Tag as PFD.Streams.StreamControl; ProcessUnitControl unit = tempMI.Tag as ProcessUnitControl; // Get a reference to the comment collection IList <StickyNote> comments; if (null != stream) { comments = stream.Stream.Comments; } else { comments = unit.ProcessUnit.Comments; } // Compute the location for the new comment MathCore.Vector location = StickyNoteControl.ComputeNewCommentNoteLocation( m_canvas, tempMI.Tag, 100.0, 100.0); // Create the new sticky note and add it to the workspace. Event handlers will update // the UI appropriately StickyNote sn = new StickyNote() { Width = 100.0, Height = 100.0, LocationX = location.X, LocationY = location.Y }; comments.Add(sn); // Add an undo that will remove the comment m_workspace.AddUndo(new UndoRedoCollection("Undo creation of comment", new RemoveComment(comments, comments.IndexOf(sn)))); // Make sure to remove the popup menu from the canvas m_canvas.Children.Remove(m_contextMenu); m_contextMenu = null; // Flip back to the default state for the canvas (null) m_canvas.CurrentState = null; }; string objName = "selected object"; if (m_canvas.SelectedElement is ProcessUnitControl) { objName = (m_canvas.SelectedElement as ProcessUnitControl).ProcessUnit.Label; } else if (m_canvas.SelectedElement is ChemProV.PFD.Streams.StreamControl) { objName = "selected stream"; } // Add a new menu item to hide all comments menuItem = new MenuItem(); menuItem.Header = "Hide all comments for " + objName; menuItem.Tag = m_canvas.SelectedElement; newContextMenu.Items.Add(menuItem); menuItem.Click += delegate(object sender, RoutedEventArgs e) { MenuItem tempMI = sender as MenuItem; (tempMI.Tag as UI.ICommentControlManager).HideAllComments(); // Make sure to remove the popup menu from the canvas m_canvas.Children.Remove(m_contextMenu); m_contextMenu = null; // Flip back to the default state for the canvas (null) m_canvas.CurrentState = null; }; // Add one to show all comments too menuItem = new MenuItem(); menuItem.Header = "Show all comments for " + objName; menuItem.Tag = m_canvas.SelectedElement; newContextMenu.Items.Add(menuItem); menuItem.Click += delegate(object sender, RoutedEventArgs e) { MenuItem tempMI = sender as MenuItem; (tempMI.Tag as UI.ICommentControlManager).ShowAllComments(); // Make sure to remove the popup menu from the canvas m_canvas.Children.Remove(m_contextMenu); m_contextMenu = null; // Flip back to the default state for the canvas (null) m_canvas.CurrentState = null; }; }
/// <summary> /// Every stream has a source and destination process unit. This method determines whether or /// not the specified unit is a valid destination. This may depend on multiple things, such /// as the type of the stream and whether or not the process unit can accept more incoming /// streams. /// </summary> /// <returns>True if the unit is a valid destination, false otherwise.</returns> public bool IsValidDestination(ProcessUnitControl unit) { return(m_stream.IsValidDestination((unit as ProcessUnitControl).ProcessUnit)); }
public void MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // If the stream is null then we don't process events if (null == m_stream) { return; } Point p = e.GetPosition(m_canvas); // We handle things in a special way if we're creating a stream. If the mouse is // let up near the source location then we go to "click-click" creation mode // instead of "click-drag-release" creation mode. MathCore.Vector v = new Vector(p.X, p.Y); if (m_creatingStream && (v - m_stream.SourceLocation).Length < 20.0) { // Ignore this event and wait for the next mouse down return; } // Clear the border color if we had set one if (null != m_changedBorderColor) { m_changedBorderColor.SetBorderColor(ProcessUnitBorderColor.NoBorder); m_changedBorderColor = null; } // If the mouse is let up over a process unit that we cannot connect to, then send the // endpoint back to where it was originally. ProcessUnitControl puc = m_canvas.GetChildAt(p, m_dragIcon) as ProcessUnitControl; if (null != puc) { if ((m_dragIcon.IsSource && object.ReferenceEquals(puc.ProcessUnit, m_stream.Source)) || (!m_dragIcon.IsSource && object.ReferenceEquals(puc.ProcessUnit, m_stream.Destination))) { // This means we've already connected and we're good to go } else if (!m_dragIcon.CanConnectTo(puc)) { // Set the state back to what it was when we started if (m_dragIcon.IsSource) { m_stream.SourceLocation = m_startLocation; m_stream.Source = m_connectedToOnStart; } else { m_stream.DestinationLocation = m_startLocation; m_stream.Destination = m_connectedToOnStart; } //m_stream = null; //Core.App.ControlPalette.SwitchToSelect(); //return; } } StateEnding(); Core.App.ControlPalette.SwitchToSelect(); }
public void MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // If the canvas reference is null then we ignore mouse events if (null == m_canvas) { return; } // Here's where we need to flip over to the MovingStreamEndpoint state. We start by // finding out if we clicked on a process unit or not Point location = e.GetPosition(m_canvas); // Clear the border if we'd previously set one if (null != m_puWithAlteredBorderColor) { m_puWithAlteredBorderColor.SetBorderColor(ProcessUnitBorderColor.NoBorder); m_puWithAlteredBorderColor = null; } // Remove the floating icon m_canvas.RemoveChild(m_sourcePlacementIcon); m_sourcePlacementIcon = null; // Get a reference to the workspace Workspace ws = m_canvas.GetWorkspace(); // See if we clicked on a valid destination object ProcessUnitControl gpu = m_canvas.GetChildAt(location, m_sourcePlacementIcon) as ProcessUnitControl; if (null == gpu) { // This means that we clicked in an area where there's no process unit that we have // to attach to. m_stream.SourceLocation = new MathCore.Vector(location.X, location.Y); m_stream.DestinationLocation = m_stream.SourceLocation + (new MathCore.Vector(0, 20.0)); ws.AddStream(m_stream); // We need an undo to remove the stream that we just added. Note that we're going to switch // over to a different state below and that creates and undo as well. This is fine since // it allows you to undo the destination placement and stream creation separately. ws.AddUndo(new UndoRedoCollection("Undo stream creation", new Logic.Undos.RemoveStream(m_stream))); } else if (gpu.ProcessUnit.CanAcceptOutgoingStream(m_stream)) { // Setup the stream and add it to the workspace m_stream.SourceLocation = new MathCore.Vector(location.X, location.Y); m_stream.DestinationLocation = m_stream.SourceLocation + (new MathCore.Vector(0, 35.0)); m_stream.Source = gpu.ProcessUnit; ws.AddStream(m_stream); // Attach the outgoing stream to the process unit after we've added the stream to // the workspace gpu.ProcessUnit.AttachOutgoingStream(m_stream); // We've linked up the stream and added it to the workspace. Now create an undo that // does the opposite ws.AddUndo(new UndoRedoCollection("Undo stream creation", new Logic.Undos.DetachOutgoingStream(gpu.ProcessUnit, m_stream), new Logic.Undos.RemoveStream(m_stream))); } else { // This means we clicked on a process unit that we cannot connect to. In this case // we want to cancel everything. This is easy since we haven't modified the workspace, // so all we have to do it switch back to select mode. m_palette.SwitchToSelect(); return; } // Get the stream control that the DrawingCanvas should have added PFD.Streams.StreamControl streamControl = m_canvas.GetStreamControl(m_stream); // Tell it to hide the table streamControl.HideTable(); // Set references to null to indicate that this state should no longer process mouse input // messages after this. We are finishing up right here. DrawingCanvas c = m_canvas; m_canvas = null; m_stream = null; // Switch back to select mode m_palette.SwitchToSelect(); // Flip over to the state where we position the stream destination c.CurrentState = new MovingStreamEndpoint(streamControl.DestinationDragIcon, c, true); }
public void StateEnding() { // If the stream is null then we don't process events if (null == m_stream) { return; } // Clear the border color if we had set one if (null != m_changedBorderColor) { m_changedBorderColor.SetBorderColor(ProcessUnitBorderColor.NoBorder); m_changedBorderColor = null; } // Create an undo Workspace ws = m_canvas.GetWorkspace(); if (m_dragIcon.IsSource) { // There are 4 cases for what could have happened: // 1. Source was originally null and still is // 2. Source was originally null and now isn't // 3. Source was originally non-null and now is null // 4. Source was originally non-null and still is non-null // 4a. It is the same // 4b. It is different if (null == m_connectedToOnStart && null == m_stream.Source) { // This is just a move of the endpoint from one location to another ws.AddUndo(new UndoRedoCollection("Undo moving stream source", new Logic.Undos.SetStreamSourceLocation(m_stream, m_startLocation))); } else if (null == m_connectedToOnStart && null != m_stream.Source) { ws.AddUndo(new UndoRedoCollection("Undo changing stream source", new Logic.Undos.SetStreamSource(m_stream, null, m_stream.Source, m_startLocation), new Logic.Undos.DetachOutgoingStream(m_stream.Source, m_stream))); } else if (null != m_connectedToOnStart && null == m_stream.Source) { ws.AddUndo(new UndoRedoCollection("Undo detaching stream source", new Logic.Undos.SetStreamSource(m_stream, m_connectedToOnStart, null, m_stream.SourceLocation), new Logic.Undos.AttachOutgoingStream(m_connectedToOnStart, m_stream))); } else { // Only take action if we've changed the source if (!object.ReferenceEquals(m_connectedToOnStart, m_stream.Source)) { ws.AddUndo(new UndoRedoCollection("Undo changing stream source", new Logic.Undos.SetStreamSource(m_stream, m_connectedToOnStart, m_stream.Source, m_stream.SourceLocation), new Logic.Undos.DetachOutgoingStream(m_stream.Source, m_stream), new Logic.Undos.AttachOutgoingStream(m_connectedToOnStart, m_stream))); } } } else { // There are 4 cases for what could have happened: // 1. Destination was originally null and still is // 2. Destination was originally null and now isn't // 3. Destination was originally non-null and now is null // 4. Destination was originally non-null and still is non-null // 4a. It is the same // 4b. It is different if (null == m_connectedToOnStart && null == m_stream.Destination) { // This is just a move of the endpoint from one location to another ws.AddUndo(new UndoRedoCollection("Undo moving stream destination", new Logic.Undos.SetStreamDestinationLocation(m_stream, m_startLocation))); } else if (null == m_connectedToOnStart && null != m_stream.Destination) { ws.AddUndo(new UndoRedoCollection("Undo changing stream destination", new Logic.Undos.SetStreamDestination(m_stream, null, m_stream.Destination, m_startLocation), new Logic.Undos.DetachIncomingStream(m_stream.Destination, m_stream))); } else if (null != m_connectedToOnStart && null == m_stream.Destination) { ws.AddUndo(new UndoRedoCollection("Undo detaching stream destination", new Logic.Undos.SetStreamDestination(m_stream, m_connectedToOnStart, null, m_stream.DestinationLocation), new Logic.Undos.AttachIncomingStream(m_connectedToOnStart, m_stream))); } else { // Only take action if we've changed the destination if (!object.ReferenceEquals(m_connectedToOnStart, m_stream.Destination)) { ws.AddUndo(new UndoRedoCollection("Undo changing stream destination", new Logic.Undos.SetStreamDestination(m_stream, m_connectedToOnStart, m_stream.Destination, m_stream.DestinationLocation), new Logic.Undos.DetachIncomingStream(m_stream.Destination, m_stream), new Logic.Undos.AttachIncomingStream(m_connectedToOnStart, m_stream))); } } } if (m_creatingStream) { // Tell the stream control to show the table m_dragIcon.ParentStream.ShowTable(true); } // Set the stream reference to null to end this state m_stream = null; }
/// <summary> /// Every stream has a source and destination process unit. This method determines whether or /// not the specified unit is a valid source. This may depend on multiple things, such /// as the type of the stream and whether or not the process unit can accept more outgoing /// streams. /// </summary> /// <returns>True if the unit is a valid source, false otherwise.</returns> public bool IsValidSource(ProcessUnitControl unit) { return(m_stream.IsValidSource((unit as ProcessUnitControl).ProcessUnit)); }
public void MouseMove(object sender, MouseEventArgs e) { // If the stream is null then we don't process events if (null == m_stream) { return; } // Get the mouse position relative to the canvas Point p = e.GetPosition(m_canvas); // Clear the border color if we had set one if (null != m_changedBorderColor) { m_changedBorderColor.SetBorderColor(ProcessUnitBorderColor.NoBorder); m_changedBorderColor = null; } // Find out if we're hovering over a process unit ProcessUnitControl lpu = m_canvas.GetChildAt(p, m_dragIcon) as ProcessUnitControl; if (null == lpu) { // All we need to do on a mouse move is make the changes in the m_stream data structure. The // application is designed such that UI controls monitor changes in these data structures and // update themselves appropriately. if (m_dragIcon.IsSource) { // If the source is not null, we need to disconnect if (null != m_stream.Source) { m_stream.Source.DetachOutgoingStream(m_stream); m_stream.Source = null; } m_stream.SourceLocation = new Vector(p.X, p.Y); } else { // If the destination is not null, we need to disconnect if (null != m_stream.Destination) { m_stream.Destination.DetachIncomingStream(m_stream); m_stream.Destination = null; } m_stream.DestinationLocation = new Vector(p.X, p.Y); } } else { // We are hovering over a process unit m_changedBorderColor = lpu; if (m_dragIcon.IsSource) { if (object.ReferenceEquals(m_stream.Source, lpu.ProcessUnit)) { // This means that the process unit we're dragging the source icon over is // already set as the source, so we don't have to do anything. } else if (lpu.ProcessUnit.CanAcceptOutgoingStream(m_stream)) { // If we had a non-null source then disconnect if (null != m_stream.Source) { m_stream.Source.DetachOutgoingStream(m_stream); } m_stream.Source = lpu.ProcessUnit; lpu.ProcessUnit.AttachOutgoingStream(m_stream); // Set the border color to indicate that we can make this connection lpu.SetBorderColor(ProcessUnitBorderColor.AcceptingStreams); } else { // If we had a non-null source then disconnect if (null != m_stream.Source) { m_stream.Source.DetachOutgoingStream(m_stream); m_stream.Source = null; } // This means that the connection cannot be made lpu.SetBorderColor(ProcessUnitBorderColor.NotAcceptingStreams); m_stream.SourceLocation = new Vector(p.X, p.Y); } } else { if (object.ReferenceEquals(m_stream.Destination, lpu.ProcessUnit)) { // This means that the process unit we're dragging the destination icon over // is already set as the destination, so we don't have to do anything. } else if (lpu.ProcessUnit.CanAcceptIncomingStream(m_stream)) { // If we had a non-null destination then disconnect if (null != m_stream.Destination) { m_stream.Destination.DetachIncomingStream(m_stream); } m_stream.Destination = lpu.ProcessUnit; lpu.ProcessUnit.AttachIncomingStream(m_stream); // Set the border color to indicate that we can make this connection lpu.SetBorderColor(ProcessUnitBorderColor.AcceptingStreams); } else { // If we had a non-null destination then disconnect if (null != m_stream.Destination) { m_stream.Destination.DetachIncomingStream(m_stream); m_stream.Destination = null; } // This means that the connection cannot be made lpu.SetBorderColor(ProcessUnitBorderColor.NotAcceptingStreams); m_stream.DestinationLocation = new Vector(p.X, p.Y); } } } }