Пример #1
0
        public static StreamControl CreateOnCanvas(DrawingCanvas canvas, AbstractStream stream)
        {
            StreamControl streamControl = new StreamControl(canvas, stream);

            canvas.AddNewChild(streamControl);
            return(streamControl);
        }
        public ChangeStreamNumberWindow(AbstractStream stream, Workspace workspace)
        {
            InitializeComponent();

            m_stream    = stream;
            m_workspace = workspace;

            if (null != workspace)
            {
                // Make a list of integer options for stream numbers
                List <int> numOpts = new List <int>();
                int        max     = 50;
                while (0 == numOpts.Count)
                {
                    max *= 2;
                    for (int i = 1; i <= 100; i++)
                    {
                        if (null == workspace.GetStream(i) ||
                            i == stream.Id)
                        {
                            numOpts.Add(i);
                        }
                    }
                }

                // Set them as the options in the combo box
                NumberComboBox.ItemsSource  = numOpts;
                NumberComboBox.SelectedItem = stream.Id;
            }
        }
Пример #3
0
        public AttachOutgoingStream(AbstractProcessUnit processUnit, AbstractStream outgoingStream)
        {
            if (null == processUnit || null == outgoingStream)
            {
                throw new ArgumentNullException();
            }

            m_pu     = processUnit;
            m_stream = outgoingStream;
        }
Пример #4
0
        public SetStreamSourceLocation(AbstractStream stream, MathCore.Vector location)
        {
            m_stream   = stream as AbstractStream;
            m_location = location;

            // Create the opposite action to set it back to where it is now
            m_opposite            = new SetStreamSourceLocation();
            m_opposite.m_location = stream.SourceLocation;
            m_opposite.m_opposite = this;
            m_opposite.m_stream   = m_stream;
        }
Пример #5
0
        private static void DeleteStreamWithUndo(ChemProV.PFD.Streams.StreamControl stream,
                                                 DrawingCanvas canvas)
        {
            AbstractStream s = stream.Stream;

            // Special case: the old version (before I rewrote a bunch of logic) didn't let
            // you delete heat streams whose destination was a heat exchanger with utility.
            // I will keep this functionality.
            if (s is HeatStream && s.Destination is HeatExchangerWithUtility)
            {
                return;
            }

            // We need to build a list of undos
            List <IUndoRedoAction> actions = new List <IUndoRedoAction>();

            if (null != s.Source)
            {
                // If the stream has a non-null source then we need to detach it and
                // make sure the undo would reattach it
                actions.Add(new Logic.Undos.AttachOutgoingStream(s.Source, s));
                actions.Add(new Logic.Undos.SetStreamSource(s, s.Source, null, s.SourceLocation));

                // Do the detachment so that the process unit (which is staying around) won't
                // have an outgoing stream that's been deleted
                s.Source.DetachOutgoingStream(s);
                s.Source = null;
            }
            if (null != s.Destination)
            {
                // If the stream has a non-null destination then we need to detach it and
                // make sure the undo would reattach it
                actions.Add(new Logic.Undos.AttachIncomingStream(s.Destination, s));
                actions.Add(new Logic.Undos.SetStreamDestination(s, s.Destination, null, s.DestinationLocation));

                // Do the detachment so that the process unit (which is staying around) won't
                // have an incoming stream that's been deleted
                s.Destination.DetachIncomingStream(s);
                s.Destination = null;
            }

            // In all cases we will need to add the stream back to the workspace
            actions.Add(new Logic.Undos.AddToWorkspace(stream.Stream));

            // Delete the stream from the workspace. Event handlers will take care of updating the UI.
            canvas.GetWorkspace().RemoveStream(stream.Stream);

            // Add the undo that we built
            canvas.GetWorkspace().AddUndo(
                new UndoRedoCollection("Undo deletion of stream", actions.ToArray()));
        }
Пример #6
0
        public SetStreamDestination(AbstractStream stream, AbstractProcessUnit destForThis,
                                    AbstractProcessUnit destForOpposite, MathCore.Vector location)
        {
            m_stream   = stream as AbstractStream;
            m_pu       = destForThis;
            m_location = location;

            // Create the opposite action
            m_opposite            = new SetStreamDestination();
            m_opposite.m_location = location;
            m_opposite.m_opposite = this;
            m_opposite.m_pu       = destForOpposite;
            m_opposite.m_stream   = m_stream;
        }
Пример #7
0
        public SetStreamSource(AbstractStream stream, AbstractProcessUnit sourceForThis,
                               AbstractProcessUnit sourceForOpposite, MathCore.Vector locationForDSE)
        {
            m_stream   = stream as AbstractStream;
            m_pu       = sourceForThis;
            m_location = locationForDSE;

            // Create the opposite action
            m_opposite            = new SetStreamSource();
            m_opposite.m_location = locationForDSE;
            m_opposite.m_opposite = this;
            m_opposite.m_pu       = sourceForOpposite;
            m_opposite.m_stream   = m_stream;
        }
Пример #8
0
        public PFD.Streams.StreamControl GetStreamControl(AbstractStream stream)
        {
            foreach (UIElement uie in Children)
            {
                PFD.Streams.StreamControl s = uie as PFD.Streams.StreamControl;
                if (null != s)
                {
                    if (Object.ReferenceEquals(s.Stream, stream))
                    {
                        return(s);
                    }
                }
            }

            return(null);
        }
Пример #9
0
        public MovingStreamEndpoint(DraggableStreamEndpoint endpoint,
                                    DrawingCanvas canvas, bool creatingStream)
        {
            m_dragIcon       = endpoint;
            m_canvas         = canvas;
            m_creatingStream = creatingStream;
            m_stream         = endpoint.ParentStream.Stream;

            if (m_dragIcon.IsSource)
            {
                m_startLocation      = m_stream.SourceLocation;
                m_connectedToOnStart = m_stream.Source;
            }
            else
            {
                m_startLocation      = m_stream.DestinationLocation;
                m_connectedToOnStart = m_stream.Destination;
            }
        }
Пример #10
0
        private void WorkspaceStreamsCollectionChanged(object sender, EventArgs e)
        {
            // Remove previous event listeners
            foreach (TreeViewItem child in StreamsDebugNode.Items)
            {
                AbstractStream stream = child.Tag as AbstractStream;
                stream.PropertyChanged -= DebugStream_PropertyChanged;
            }

            // Clear and rebuild
            StreamsDebugNode.Items.Clear();
            foreach (AbstractStream stream in m_workspace.Streams)
            {
                StreamsDebugNode.Items.Add(new TreeViewItem()
                {
                    Header = stream.UIDString + "\n(src @ " + stream.SourceLocation.ToString() +
                             ")\n(dst @ " + stream.DestinationLocation.ToString() + ")",

                    Tag = stream
                });

                stream.PropertyChanged += new PropertyChangedEventHandler(DebugStream_PropertyChanged);
            }
        }
Пример #11
0
        private void DebugStream_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("SourceLocation") || e.PropertyName.Equals("DestinationLocation"))
            {
                AbstractStream stream = sender as AbstractStream;

                // Find the tree view item for this stream
                TreeViewItem tvi = null;
                foreach (TreeViewItem tviTemp in StreamsDebugNode.Items)
                {
                    if (object.ReferenceEquals(tviTemp.Tag, stream))
                    {
                        tvi = tviTemp;
                        break;
                    }
                }

                if (null != tvi)
                {
                    tvi.Header = stream.UIDString + "\n(src @ " + stream.SourceLocation.ToString() +
                                 ")\n(dst @ " + stream.DestinationLocation.ToString() + ")";
                }
            }
        }
Пример #12
0
        public void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // We don't process messages if the placement icon is null
            if (null == m_placementIcon)
            {
                return;
            }

            // Handle heat exchanger with utility as a special case
            if (m_type.Equals(typeof(HeatExchangerWithUtility)))
            {
                MLBD_HEWU(sender, e);
                return;
            }

            // Start by getting the mouse position
            Point pos = e.GetPosition(m_canvas);

            MathCore.Vector vPos = new MathCore.Vector(pos.X, pos.Y);

            // See if we have a DraggableStreamEndpoint where we clicked
            DraggableStreamEndpoint endpoint = m_canvas.GetChildAt(pos, m_placementIcon) as
                                               DraggableStreamEndpoint;

            // Remove the placement icon and then set it to null to indicate state completion
            m_canvas.RemoveChild(m_placementIcon);
            m_placementIcon = null;

            // Determine a unique identifier for the process unit
            int uid;

            do
            {
                uid = AbstractProcessUnit.GetNextUID();
            }while (null != m_workspace.GetProcessUnit(uid));

            // If there's not an endpoint, we create the process unit with no stream connections
            if (null == endpoint)
            {
                AbstractProcessUnit unit = (AbstractProcessUnit)Activator.CreateInstance(
                    m_type, uid);

                // Set the location
                unit.Location = new MathCore.Vector(pos.X, pos.Y);

                // Add it to the workspace
                m_workspace.AddProcessUnit(unit);

                // Add an undo that will remove it
                m_workspace.AddUndo(new UndoRedoCollection("Undo process unit creation",
                                                           new ChemProV.Logic.Undos.RemoveProcessUnit(unit)));

                m_canvas.SelectedElement = null;

                // Tell the control palette to switch back to select mode and then return
                m_palette.SwitchToSelect();
                return;
            }

            // Otherwise, if we HAVE clicked on an endpoint...

            // Check to see if we can't connect this way
            AbstractProcessUnit temp = (AbstractProcessUnit)
                                       Activator.CreateInstance(m_type, -1);

            if (!endpoint.CanConnectTo(temp))
            {
                // The usability here may be debatable. But for now we'll cancel placement and
                // give the user an error message
                m_palette.SwitchToSelect();
                Core.App.MessageBox("The stream endpoint that you clicked cannot connect with " +
                                    "the process unit that you were placing.");
                return;
            }

            // Otherwise, if we CAN connect this way...

            // Create the process unit
            AbstractProcessUnit apu = (AbstractProcessUnit)
                                      Activator.CreateInstance(m_type, uid);

            // Make the undo and then the actual attachment
            if (DraggableStreamEndpoint.EndpointType.StreamDestination == endpoint.Type)
            {
                // Set the location
                apu.Location = endpoint.ParentStream.Stream.DestinationLocation;

                // Create an undo that sets the stream destination back to what it was and removes the
                // process unit
                m_workspace.AddUndo(new UndoRedoCollection("Undo process unit creation + attachment",
                                                           new Logic.Undos.SetStreamDestination(endpoint.ParentStream.Stream, null, apu, vPos),
                                                           new Logic.Undos.RemoveProcessUnit(apu)));

                apu.AttachIncomingStream(endpoint.ParentStream.Stream);
                endpoint.ParentStream.Stream.Destination = apu;
            }
            else
            {
                // Set the location
                apu.Location = endpoint.ParentStream.Stream.SourceLocation;

                // Create an undo that sets the stream source back to what it was and removes the
                // process unit from the canvas
                AbstractStream stream = endpoint.ParentStream.Stream;
                m_workspace.AddUndo(new UndoRedoCollection("Undo process unit creation + attachment",
                                                           new Logic.Undos.SetStreamSource(stream, null, apu, stream.SourceLocation),
                                                           new Logic.Undos.RemoveProcessUnit(apu)));

                apu.AttachOutgoingStream(endpoint.ParentStream.Stream);
                endpoint.ParentStream.Stream.Source = apu;
            }

            // Don't forget to add the process unit to the workspace. Event handlers will update the
            // UI appropriately.
            m_workspace.AddProcessUnit(apu);

            m_canvas.SelectedElement = null;

            // Go back to select mode
            m_palette.SwitchToSelect();
        }
Пример #13
0
 public RemoveStream(AbstractStream streamToRemove)
 {
     m_streamToRemove = streamToRemove;
 }
Пример #14
0
        private StreamControl(DrawingCanvas canvas, AbstractStream stream)
        {
            m_canvas = canvas;
            m_stream = stream;

            InitializeComponent();

            if (null != canvas && null != stream)
            {
                // Create the brush for the stream line
                if (stream is HeatStream)
                {
                    m_streamLineNotSelected = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    m_streamLineNotSelected = new SolidColorBrush(Colors.Black);
                }

                // Create the drag handle for the source
                m_sourceDragIcon = new DraggableStreamEndpoint(
                    DraggableStreamEndpoint.EndpointType.StreamSource,
                    this, canvas);
                m_sourceDragIcon.Width    = m_sourceDragIcon.Height = 20.0;
                m_sourceDragIcon.Location = new Point(m_stream.SourceLocation.X, m_stream.SourceLocation.Y);
                // Add it to the canvas
                m_canvas.AddNewChild(m_sourceDragIcon);
                // Set the Z-index
                m_sourceDragIcon.SetValue(Canvas.ZIndexProperty, 2);
                // Setup mouse events
                m_sourceDragIcon.MouseLeftButtonDown += new MouseButtonEventHandler(DragIcon_MouseLeftButtonDown);

                // Create the drag handle for the destination
                m_dstDragIcon = new DraggableStreamEndpoint(
                    DraggableStreamEndpoint.EndpointType.StreamDestination,
                    this, canvas);
                // Add it to the canvas
                m_canvas.AddNewChild(m_dstDragIcon);
                // Set the Z-index
                m_dstDragIcon.SetValue(Canvas.ZIndexProperty, 2);
                // Show it if there's no destination, hide it otherwise
                m_dstDragIcon.Visibility = (null == m_stream.Destination) ?
                                           Visibility.Visible : System.Windows.Visibility.Collapsed;
                // Setup mouse events
                m_dstDragIcon.MouseLeftButtonDown += new MouseButtonEventHandler(DragIcon_MouseLeftButtonDown);

                // Create the arrow polygon control
                m_arrow = new Polygon();
                // Set the fill
                m_arrow.Fill = m_streamLineNotSelected;
                // Add it to the canvas
                m_canvas.AddNewChild(m_arrow);
                // Set the Z-index
                m_arrow.SetValue(Canvas.ZIndexProperty, 2);
                // Add 3 points/vertices
                m_arrow.Points.Add(new Point());
                m_arrow.Points.Add(new Point());
                m_arrow.Points.Add(new Point());
                // Hide it if there's no destination
                if (null == m_stream.Destination)
                {
                    m_arrow.Visibility = Visibility.Collapsed;
                }
                // Setup mouse events
                if (!(m_stream.Destination is HeatExchangerWithUtility))
                {
                    m_arrow.MouseLeftButtonDown += new MouseButtonEventHandler(DestinationArrow_MouseLeftButtonDown);
                }

                UpdateStreamLocation();

                // Create the table
                CreatePropertiesTable(m_stream.PropertiesTable);

                // Watch for when the table location changes
                m_stream.PropertiesTable.PropertyChanged += new PropertyChangedEventHandler(PropertiesTable_PropertyChanged);

                // Add it to the canvas and set it up
                m_canvas.AddNewChild(m_table as UIElement);

                UserControl tableAsUiElement = m_table as UserControl;

                //This sets the tables index to the greatest so it will be above everything
                tableAsUiElement.SetValue(System.Windows.Controls.Canvas.ZIndexProperty, 3);

                tableAsUiElement.MouseLeftButtonDown += new MouseButtonEventHandler((canvas as DrawingCanvas).MouseLeftButtonDownHandler);
                tableAsUiElement.MouseLeftButtonUp   += new MouseButtonEventHandler((canvas as DrawingCanvas).MouseLeftButtonUpHandler);

                // Hook up event listeners to the stream if non-null. We need to monitor:
                //  1. Changes in the comment collection
                //  2. Changes to the source process units properties (position)
                //  3. Changes to the destination process units properties (position)
                //  4. Changes to the source or destination references

                // 1.
                // Setup the event listener for the comment collection. It is the responsibility of this
                // control to create and manage the sticky note controls for its comments
                m_stream.Comments.CollectionChanged += Comments_CollectionChanged;
                // Invoke the callback to create sticky notes for comments
                Comments_CollectionChanged(m_stream.Comments, null);

                // 2.
                if (null != stream.Source)
                {
                    m_sourceEventItem              = stream.Source;
                    stream.Source.PropertyChanged += this.SourceOrDest_PropertyChanged;
                }

                // 3.
                if (null != stream.Destination)
                {
                    m_destEventItem = stream.Destination;
                    stream.Destination.PropertyChanged += this.SourceOrDest_PropertyChanged;
                }

                // 4.
                stream.PropertyChanged += new PropertyChangedEventHandler(Stream_PropertyChanged);
            }
        }
Пример #15
0
        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;
        }
Пример #16
0
        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);
        }
Пример #17
0
        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;
            }
        }
Пример #18
0
        public PlacingNewStream(UI.ControlPalette sender, DrawingCanvas canvas, StreamType streamType)
        {
            // Quick error check on parameters
            if (null == sender || null == canvas)
            {
                throw new ArgumentNullException();
            }
            if (StreamType.Chemical != streamType && StreamType.Heat != streamType)
            {
                // To save us from problems with future changes
                throw new NotImplementedException();
            }

            m_palette = sender;
            m_canvas  = canvas;

            // Create the stream (data structure, not control). Take care to pick an ID that's not
            // already in use.
            int newID;

            do
            {
                newID = AbstractStream.GetNextUID();
            }while (canvas.GetWorkspace().StreamExists(newID));
            if (StreamType.Chemical == streamType)
            {
                m_stream = new ChemicalStream(newID);
            }
            else
            {
                m_stream = new HeatStream(newID);
            }

            // Create the table
            m_stream.PropertiesTable = new StreamPropertiesTable(m_stream);

            // Create the default row if we have a heat stream. There is no default row
            // for chemical streams
            if (StreamType.Heat == streamType)
            {
                // Add a default row if it's not already there
                if (0 == m_stream.PropertiesTable.RowCount)
                {
                    m_stream.PropertiesTable.AddNewRow();
                }

                // Choose a default label
                m_stream.PropertiesTable.Rows[0].Label = "Q" + m_stream.Id.ToString();

                // Select default units
                (m_stream.PropertiesTable.Rows[0] as HeatStreamData).SelectedUnits =
                    HeatStreamData.EnergyUnitOptions[0];

                // Flag it as not renamed by the user yet
                m_stream.PropertiesTable.Rows[0].UserHasRenamed = false;
            }

            // Create the source placement icon and add it to the canvas
            m_sourcePlacementIcon = new Image();
            Uri         uri = new Uri("/UI/Icons/pu_source.png", UriKind.Relative);
            ImageSource img = new System.Windows.Media.Imaging.BitmapImage(uri);

            m_sourcePlacementIcon.SetValue(Image.SourceProperty, img);
            m_canvas.AddNewChild(m_sourcePlacementIcon);
            m_sourcePlacementIcon.SetValue(Canvas.ZIndexProperty, 4);
        }
Пример #19
0
        public void SetCommentObject(StickyNote comment, object parent)
        {
            if (null != m_sticky)
            {
                // Remove event handler before changing this value
                m_sticky.PropertyChanged -= this.StickyNote_PropertyChanged;
            }
            if (null != m_basic)
            {
                m_basic.OnTextChanged -= this.BasicComment_OnTextChanged;
            }

            // IMPORTANT: Unsubscribe from parent control property changes (if applicable)
            if (null != m_parentObject)
            {
                if (m_parentObject is AbstractProcessUnit)
                {
                    (m_parentObject as AbstractProcessUnit).PropertyChanged -= this.ParentPU_PropertyChanged;
                }
                else if (m_parentObject is AbstractStream)
                {
                    (m_parentObject as AbstractStream).PropertyChanged -= this.ParentStream_PropertyChanged;
                }
            }

            // Store references
            m_basic        = null;
            m_sticky       = comment;
            m_parentObject = parent;

            AbstractStream      parentStream = parent as AbstractStream;
            AbstractProcessUnit parentAPU    = parent as AbstractProcessUnit;

            // Update the UI elements if the comment is not null
            if (null != m_sticky)
            {
                CommentTextBox.Text   = m_sticky.Text;
                UserNameLabel.Content = m_sticky.UserName;

                // Subsribe to property changes
                m_sticky.PropertyChanged += this.StickyNote_PropertyChanged;

                // Allow editing but not deletion
                CommentTextBox.IsReadOnly = false;
                XLabel.Visibility         = System.Windows.Visibility.Collapsed;

                // Show or hide the icon based on the parent
                if (null != parentStream)
                {
                    // Get the right icon for this type of stream
                    string      iconSource = PFD.Streams.StreamControl.GetIconSource(parent.GetType());
                    BitmapImage bmp        = new BitmapImage();
                    bmp.UriSource = new Uri(iconSource, UriKind.Relative);
                    IconImage.SetValue(Image.SourceProperty, bmp);

                    // Make sure the icon is visible
                    IconImage.Visibility = System.Windows.Visibility.Visible;
                    TitleBarGrid.ColumnDefinitions[0].Width = new GridLength(20.0);

                    // Give the icon a tooltip that tells what this is a comment for
                    ToolTipService.SetToolTip(IconImage, "Comment for stream #" +
                                              parentStream.Id);

                    // Subscribe to property changes for the stream
                    parentStream.PropertyChanged += new PropertyChangedEventHandler(ParentStream_PropertyChanged);
                }
                else if (null != parentAPU)
                {
                    // Get the right icon for this type of process unit
                    string      iconSource = ProcessUnitControl.GetIconSource(parent.GetType());
                    BitmapImage bmp        = new BitmapImage();
                    bmp.UriSource = new Uri(iconSource, UriKind.Relative);
                    IconImage.SetValue(Image.SourceProperty, bmp);

                    // Make sure the icon is visible
                    IconImage.Visibility = System.Windows.Visibility.Visible;
                    TitleBarGrid.ColumnDefinitions[0].Width = new GridLength(20.0);

                    // Give the icon a tooltip that tells what this is a comment for
                    ToolTipService.SetToolTip(IconImage, "Comment for " +
                                              (m_parentObject as AbstractProcessUnit).Label);

                    // Subscribe to property changes for the process unit
                    parentAPU.PropertyChanged += new PropertyChangedEventHandler(ParentPU_PropertyChanged);
                }
                else
                {
                    // Make sure the icon is hidden
                    IconImage.Visibility = System.Windows.Visibility.Collapsed;
                    TitleBarGrid.ColumnDefinitions[0].Width = new GridLength(0.0);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Merges comments from two Xml document streams into a new output Xml document stream. Comment
        /// merging is not commutative. One document must be considered to be the parent and another a
        /// child. ALL content from the parent will appear in the output. Comments from the child
        /// document will only be written to the output if they exist for shared entities. That is, if
        /// there is a comment in the child document that is tied to a process unit with Id=GPU_30, then
        /// it will only be written the output document if the parent also contained a process unit with
        /// the same Id.
        /// </summary>
        public static void Merge(Stream parent, string parentUserNameIfNotInXml, Stream child,
                                 string childUserNameIfNotInXml, Stream output)
        {
            // We need all streams to be non-null
            if (null == parent)
            {
                throw new ArgumentNullException(
                          "Parent stream for comment merging cannot be null");
            }
            if (null == child)
            {
                throw new ArgumentNullException(
                          "Child stream for comment merging cannot be null");
            }
            if (null == output)
            {
                throw new ArgumentNullException(
                          "Output stream for comment merging cannot be null");
            }

            // Load the workspaces from the streams
            Workspace wsParent = new Workspace();

            wsParent.Load(parent);
            Workspace wsChild = new Workspace();

            wsChild.Load(child);

            // What we will do in this method is alter wsParent to contain relevant content from the
            // child workspace and then save it to the output stream.

            // Start by setting user names for comments in both workspaces. We leave the user names
            // alone if they are not null or empty but otherwise we set them to the values specified
            // by the caller.
            SetUserNameIfAbsent(wsParent, parentUserNameIfNotInXml);
            SetUserNameIfAbsent(wsChild, childUserNameIfNotInXml);

            // Start with the free-floating sticky note comments. We want to take the ones from the
            // child and add them into the parent. But we want to avoid duplicates in the process.
            foreach (StickyNote sn in wsChild.StickyNotes)
            {
                // If they have the same text and location then we'll skip
                if (WorkspaceUtility.ContainsFFSNWithValues(wsParent, sn.Text,
                                                            new MathCore.Vector(sn.LocationX, sn.LocationY)))
                {
                    continue;
                }

                // Add it to the parent
                wsParent.StickyNotes.Add(sn);
            }

            // Next do process units in the child
            foreach (AbstractProcessUnit apuChild in wsChild.ProcessUnits)
            {
                AbstractProcessUnit apuParent = wsParent.GetProcessUnit(apuChild.Id);

                // If the parent workspace doesn't contain a process unit with the same ID then we
                // skip it
                if (null == apuParent)
                {
                    continue;
                }

                foreach (StickyNote comment in apuChild.Comments)
                {
                    if (WorkspaceUtility.CollectionContainsItemWithText(apuParent.Comments, comment.Text))
                    {
                        // Skip it if there's already a comment with the same text
                        continue;
                    }

                    // Add it to the parent process unit
                    apuParent.Comments.Add(comment);
                }
            }

            // Now do streams in the child
            foreach (AbstractStream sChild in wsChild.Streams)
            {
                AbstractStream sParent = wsParent.GetStream(sChild.Id);

                // If the parent workspace doesn't contain a stream with the same ID then we
                // skip it
                if (null == sParent)
                {
                    continue;
                }

                foreach (StickyNote comment in sChild.Comments)
                {
                    if (WorkspaceUtility.CollectionContainsItemWithText(sParent.Comments, comment.Text))
                    {
                        // Skip it if there's already a comment with the same text
                        continue;
                    }

                    // Add the comment to the parent stream
                    sParent.Comments.Add(comment);
                }
            }

            // Equation comments need to be merged as well
            foreach (EquationModel emChild in wsChild.Equations)
            {
                // Get the equation object in the parent with the same ID
                EquationModel emParent = wsParent.Equations.GetById(emChild.Id);

                // If we can't find it then move on to the next
                if (null == emParent)
                {
                    continue;
                }

                // Now add each comment in the child that isn't already in the parent
                foreach (BasicComment bcChild in emChild.Comments)
                {
                    if (!emParent.ContainsComment(bcChild.CommentText))
                    {
                        emParent.Comments.Add(bcChild);
                    }
                }
            }

            // Lastly we deal with the comments for the degrees of freedom analysis. We only
            // merge in comments from the child if the analysis text is the same in both.
            if (wsParent.DegreesOfFreedomAnalysis.Text == wsChild.DegreesOfFreedomAnalysis.Text)
            {
                foreach (BasicComment bcChild in wsChild.DegreesOfFreedomAnalysis.Comments)
                {
                    if (!wsParent.DegreesOfFreedomAnalysis.ContainsComment(bcChild.CommentText))
                    {
                        wsParent.DegreesOfFreedomAnalysis.Comments.Add(bcChild);
                    }
                }
            }

            // Now that we have everything merged into the parent workspace, we just save it to the
            // output stream
            wsParent.Save(output);
        }
Пример #21
0
 public SetStreamId(AbstractStream stream, int id)
 {
     m_stream = stream;
     m_id     = id;
 }
Пример #22
0
 public DetachIncomingStream(AbstractProcessUnit processUnit, AbstractStream incomingStream)
 {
     m_pu     = processUnit;
     m_stream = incomingStream;
 }
Пример #23
0
        public void TestSaveLoad()
        {
            int       i;
            Workspace ws1  = new Workspace();
            Random    rand = new Random();

            // Add a random number of process units
            List <int> puIDs = new List <int>();
            int        numPU = rand.Next(25);

            for (i = 0; i < numPU; i++)
            {
                AbstractProcessUnit pu = new Mixer();
                ws1.AddProcessUnit(pu);
                puIDs.Add(pu.Id);
            }

            // Add a random number of chemical streams
            int numStreams = rand.Next(10);

            for (i = 0; i < numStreams; i++)
            {
                AbstractStream stream = new ChemicalStream(AbstractStream.GetNextUID());
                ws1.AddStream(stream);

                // Don't forget that the properties table needs to be created separately
                stream.PropertiesTable = new StreamPropertiesTable(stream);

                // 50% chance of connecting a destination (attempting a connect that is)
                if (0 == (rand.Next() % 2))
                {
                    AbstractProcessUnit pu = ws1.ProcessUnits[rand.Next(ws1.ProcessUnitCount)];
                    if (pu.AttachIncomingStream(stream))
                    {
                        stream.Destination = pu;
                    }
                }
            }

            // Save the workspace to a memory stream
            MemoryStream ms = new MemoryStream();

            ws1.Save(ms, "TEST_VersionNA");

            // Load to a new workspace
            Workspace ws2 = new Workspace();

            ws2.Load(ms);

            // Make sure the number of process units and streams match
            Assert.IsTrue(numPU == ws2.ProcessUnitCount,
                          "Number of process units between saved document (" + numPU.ToString() +
                          ") and loaded document (" + ws2.ProcessUnitCount.ToString() + ") do not match");
            Assert.IsTrue(numStreams == ws2.Streams.Count,
                          "Number of streams between saved document (" + numStreams.ToString() +
                          ") and loaded document (" + ws2.Streams.Count.ToString() + ") do not match");

            // Test that the incoming/outgoing streams for process units match
            foreach (AbstractProcessUnit pu1 in ws1.ProcessUnits)
            {
                AbstractProcessUnit pu2 = ws2.GetProcessUnit(pu1.Id);
                Assert.IsNotNull(pu2,
                                 "Process unit with ID=" + pu1.Id.ToString() + " from workspace 1 (saved) was not " +
                                 "found in workspace 2 (loaded).");

                // For now just compare outoging stream count
                Assert.IsTrue(pu1.OutgoingStreamCount == pu2.OutgoingStreamCount,
                              "Mis-match outgoing stream count");
            }
        }