コード例 #1
0
        public void MouseMove(object sender, MouseEventArgs e)
        {
            // Position the placement icon
            Point pos = e.GetPosition(m_canvas);

            m_placementIcon.SetValue(Canvas.LeftProperty, pos.X - 20.0);
            m_placementIcon.SetValue(Canvas.TopProperty, pos.Y - 20.0);

            // Show the placement icon if it wasn't already visible
            if (Visibility.Visible != m_placementIcon.Visibility)
            {
                m_placementIcon.Visibility = Visibility.Visible;
            }

            // Set border highlight if we're hoving over a stream endpoint
            DraggableStreamEndpoint endpoint = m_canvas.GetChildAt(pos, m_placementIcon) as
                                               DraggableStreamEndpoint;

            if (null == endpoint)
            {
                m_placementIcon.BorderThickness = new Thickness(0.0);
            }
            else
            {
                AbstractProcessUnit temp = (AbstractProcessUnit)
                                           Activator.CreateInstance(m_type, -1);
                m_placementIcon.BorderThickness = new Thickness(2.0);
                m_placementIcon.BorderBrush     = (endpoint.CanConnectTo(temp) ? s_greenBrush : s_redBrush);
            }
        }
コード例 #2
0
        public AttachOutgoingStream(AbstractProcessUnit processUnit, AbstractStream outgoingStream)
        {
            if (null == processUnit || null == outgoingStream)
            {
                throw new ArgumentNullException();
            }

            m_pu     = processUnit;
            m_stream = outgoingStream;
        }
コード例 #3
0
        /// <summary>
        /// Removes this control from the canvas. This includes removal of controls that are
        /// "attached" to this control, such as the comment sticky note controls.
        /// This is considered disposal of the control and it should not be used anymore
        /// after calling this method.
        /// </summary>
        public void RemoveSelfFromCanvas(UI.DrawingCanvas canvas)
        {
            // Unsubscribe from events (important)
            m_stream.PropertyChanged            -= this.Stream_PropertyChanged;
            m_stream.Comments.CollectionChanged -= this.Comments_CollectionChanged;
            if (null != m_sourceEventItem)
            {
                m_sourceEventItem.PropertyChanged -= this.SourceOrDest_PropertyChanged;
                m_sourceEventItem = null;
            }
            if (null != m_destEventItem)
            {
                m_destEventItem.PropertyChanged -= this.SourceOrDest_PropertyChanged;
                m_destEventItem = null;
            }
            if (null != m_table)
            {
                m_stream.PropertiesTable.PropertyChanged -= this.PropertiesTable_PropertyChanged;
            }

            canvas.RemoveChild(this);
            canvas.RemoveChild(m_sourceDragIcon);
            canvas.RemoveChild(m_dstDragIcon);
            canvas.RemoveChild(m_table);
            if (null != m_miniTable)
            {
                canvas.RemoveChild(m_miniTable);
            }
            if (null != m_square)
            {
                canvas.RemoveChild(m_square);
            }
            if (null != m_arrow)
            {
                canvas.RemoveChild(m_arrow);
            }

            // Remove all the lines
            foreach (Line line in m_lines)
            {
                canvas.RemoveChild(line);
            }
            m_lines.Clear();

            foreach (StickyNoteControl snc in m_stickyNotes)
            {
                snc.RemoveSelfFromCanvas(canvas);
            }
            m_stickyNotes.Clear();

            // Set the value to indiate that we've removed
            m_hasBeenRemoved = true;
        }
コード例 #4
0
        private void UpdateEquationModelElements(EquationModel equation)
        {
            List <object> relevantUnits = new List <object>();

            //supply different PFD elements to the model depending on its scope
            switch (equation.Scope.Classification)
            {
            //With a single unit, all we care about is that unit and its related streams
            case EquationScopeClassification.SingleUnit:
                AbstractProcessUnit selectedUnit = (from element in m_workspace.ProcessUnits
                                                    where (element as AbstractProcessUnit).Label == equation.Scope.Name
                                                    select element).FirstOrDefault() as AbstractProcessUnit;
                if (selectedUnit != null)
                {
                    relevantUnits = GetElementAndStreams(selectedUnit);
                }
                break;

            //ChemProV doesn't currently support sub processes, but this is where
            //that logic would go
            case EquationScopeClassification.SubProcess:
                break;

            //AC: Not sure what should happen here
            case EquationScopeClassification.Unknown:
                break;

            //Pull all source and sink units as well as their streams
            case EquationScopeClassification.Overall:
            default:
                // TODO: Fix or remove

                //List<GenericProcessUnit> units = (from element in PfdElements
                //                            where element is GenericProcessUnit
                //                            &&
                //                            (
                //                             (element as GenericProcessUnit).Description == ProcessUnitDescriptions.Sink
                //                             ||
                //                             (element as GenericProcessUnit).Description == ProcessUnitDescriptions.Source
                //                            )
                //                            select element as GenericProcessUnit).ToList();
                //foreach (GenericProcessUnit unit in units)
                //{
                //    relevantUnits = relevantUnits.Union(GetElementAndStreams(unit)).ToList();
                //}
                break;
            }

            //assign the updated list to the equation
            equation.RelatedElements = relevantUnits;
        }
コード例 #5
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;
        }
コード例 #6
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;
        }
コード例 #7
0
        /// <summary>
        /// Removes this control from the canvas. This includes removal of controls that are
        /// "attached" to this control, such as the comment sticky note controls.
        /// This is considered "disposing" the control and it should not be used after this call.
        /// </summary>
        public void RemoveSelfFromCanvas(UI.DrawingCanvas owner)
        {
            // Unsubscribe from events
            m_pu.Comments.CollectionChanged -= this.CommentCollectionChanged;
            m_pu.PropertyChanged            -= this.ProcessUnit_PropertyChanged;

            owner.RemoveChild(this);
            foreach (ChemProV.UI.StickyNoteControl snc in m_stickyNotes)
            {
                snc.RemoveSelfFromCanvas(owner);
            }

            // Set the process unit reference to null
            m_pu = null;
        }
コード例 #8
0
        /// <summary>
        /// Use CreateOnCanvas
        /// </summary>
        private ProcessUnitControl(DrawingCanvas canvas, AbstractProcessUnit processUnit)
        {
            InitializeComponent();

            // Store a reference to the canvas and process unit
            m_pu     = processUnit;
            m_canvas = canvas;

            // Create the icon image
            BitmapImage bmp = new BitmapImage();

            bmp.UriSource = new Uri(GetIconSource(processUnit.GetType()), UriKind.Relative);
            ProcessUnitImage.SetValue(Image.SourceProperty, bmp);

            // Set the background color based on the subprocess
            Color clr;

            if (Core.App.TryParseColor(m_pu.Subprocess, out clr))
            {
                ProcessUnitBorder.Background = new SolidColorBrush(clr);
            }

            ProcessUnitNameText.MouseLeftButtonDown += new MouseButtonEventHandler(ProcessUnitNameText_MouseLeftButtonDown);
            ProcessUnitNameBox.MouseLeftButtonDown  += new MouseButtonEventHandler(ProcessUnitNameBox_MouseLeftButtonDown);
            ProcessUnitNameBox.LostFocus            += new RoutedEventHandler(ProcessUnitNameBox_LostFocus);
            ProcessUnitNameBox.KeyDown += new KeyEventHandler(ProcessUnitNameBox_KeyDown);

            // Create the icon image
            ProcessUnitImage.SetValue(Image.SourceProperty, ProcessUnitImage.Source);

            // Set the default label
            ProcessUnitNameText.Text = ProcessUnitNameBox.Text = m_pu.Label;

            // 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
            processUnit.Comments.CollectionChanged += CommentCollectionChanged;

            // Setup the event listener for property changes. When things like the location property
            // change, we'll need to update our position on the canvas.
            processUnit.PropertyChanged += this.ProcessUnit_PropertyChanged;

            // Just a note that we don't need to watch when the incoming or outgoing streams change
            // because that doesn't affect how we present the process unit in the UI

            // Invoke the comment change event to do the intial creation of comment controls
            CommentCollectionChanged(m_pu.Comments,
                                     new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
コード例 #9
0
        private List <object> GetElementAndStreams(AbstractProcessUnit unit)
        {
            List <object> elements = new List <object>();

            // Add the process unit as well as its incoming and outgoing streams
            elements.Add(unit);
            foreach (AbstractStream element in unit.IncomingStreams)
            {
                elements.Add(element);
            }
            foreach (AbstractStream element in unit.OutgoingStreams)
            {
                elements.Add(element);
            }
            return(elements);
        }
コード例 #10
0
        public static ProcessUnitControl CreateOnCanvas(DrawingCanvas canvas,
                                                        AbstractProcessUnit processUnit)
        {
            ProcessUnitControl pu = new ProcessUnitControl(canvas, processUnit);

            canvas.AddNewChild(pu);

            // Set the initial location
            pu.SetValue(Canvas.LeftProperty, processUnit.Location.X - pu.Width / 2.0);
            pu.SetValue(Canvas.TopProperty, processUnit.Location.Y - pu.Height / 2.0);

            // Make sure we have the right z-order
            pu.SetValue(Canvas.ZIndexProperty, 1);

            return(pu);
        }
コード例 #11
0
ファイル: DrawingCanvas.cs プロジェクト: petlyuk/CHEMPROV
        public ProcessUnitControl GetProcessUnitControl(AbstractProcessUnit unit)
        {
            foreach (UIElement uie in Children)
            {
                if (!(uie is ProcessUnitControl))
                {
                    continue;
                }

                ProcessUnitControl pu = uie as ProcessUnitControl;
                if (object.ReferenceEquals(pu.ProcessUnit, unit))
                {
                    return(pu);
                }
            }

            return(null);
        }
コード例 #12
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;
            }
        }
コード例 #13
0
        /// <summary>
        /// Determines whether or not this endpoint can connect to the specified process unit
        /// </summary>
        public bool CanConnectTo(AbstractProcessUnit processUnit)
        {
            // The logic to determine this is already implemented in the process unit. We just
            // have to identify whether we're incoming or outgoing.
            if (EndpointType.StreamDestination == m_type)
            {
                return(processUnit.CanAcceptIncomingStream(m_owner.Stream) &&
                       !object.ReferenceEquals(processUnit, m_owner.Stream.Source));
            }
            else if (EndpointType.StreamSource == m_type)
            {
                return(processUnit.CanAcceptOutgoingStream(m_owner.Stream) &&
                       !object.ReferenceEquals(processUnit, m_owner.Stream.Destination));
            }

            // If we're already connected then we cannot connect to anything else. Endpoints attach
            // to only one item.
            return(false);
        }
コード例 #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
        private void Stream_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // If we're told to ignore these then just return
            if (m_ignoreStreamPropertyChanges)
            {
                return;
            }

            // Set the ignore flag to avoid recursion
            m_ignoreStreamPropertyChanges = true;

            if (e.PropertyName.Equals("Source"))
            {
                // Unsubscribe from the old source
                if (null != m_sourceEventItem)
                {
                    m_sourceEventItem.PropertyChanged -= this.SourceOrDest_PropertyChanged;
                }

                // Keep the reference to the new source
                m_sourceEventItem = m_stream.Source;

                // Subscribe to the new source
                if (null != m_stream.Source)
                {
                    m_stream.Source.PropertyChanged += this.SourceOrDest_PropertyChanged;

                    // Set the source location to that of the source process unit
                    m_stream.SourceLocation = m_stream.Source.Location;
                }

                // Update the stream's location
                UpdateStreamLocation();
            }
            else if (e.PropertyName.Equals("Destination"))
            {
                // Unsubscribe from the old destination
                if (null != m_destEventItem)
                {
                    m_destEventItem.PropertyChanged -= this.SourceOrDest_PropertyChanged;
                }

                // Keep the reference to the new destination
                m_destEventItem = m_stream.Destination;

                // Subscribe to the new destination
                if (null != m_stream.Destination)
                {
                    m_stream.Destination.PropertyChanged += this.SourceOrDest_PropertyChanged;

                    // Hide the destination drag icon. We need to use the arrow.
                    m_dstDragIcon.Visibility = System.Windows.Visibility.Collapsed;
                }
                else
                {
                    // Null destination means we need to show the drag icon and not the arrow
                    m_dstDragIcon.Visibility = System.Windows.Visibility.Visible;
                    m_arrow.Visibility       = System.Windows.Visibility.Collapsed;
                }

                // Update the stream's location
                UpdateStreamLocation();
            }
            else if (e.PropertyName.Equals("SourceLocation"))
            {
                // Position the drag icon if the source is null
                if (null == m_stream.Source)
                {
                    m_sourceDragIcon.Location = new Point(
                        m_stream.SourceLocation.X, m_stream.SourceLocation.Y);
                }

                UpdateStreamLocation();
            }
            else if (e.PropertyName.Equals("DestinationLocation"))
            {
                // Position the drag icon if the destination is null
                if (null == m_stream.Destination)
                {
                    m_dstDragIcon.Location = new Point(
                        m_stream.DestinationLocation.X, m_stream.DestinationLocation.Y);
                }

                UpdateStreamLocation();
            }
            else if (e.PropertyName.Equals("Id"))
            {
                if (null != m_miniTable)
                {
                    m_miniTable.NameTextBlock.Text = "S" + m_stream.Id.ToString();
                }
            }

            // Reset the flag
            m_ignoreStreamPropertyChanges = false;
        }
コード例 #16
0
ファイル: SetSubprocess.cs プロジェクト: petlyuk/CHEMPROV
 public SetSubprocess(AbstractProcessUnit processUnit)
 {
     m_value = processUnit.Subprocess;
     m_pu    = processUnit;
 }
コード例 #17
0
        /// <summary>
        /// Handles mouse-left-button-down event for placing a heat exchanger with utility
        /// </summary>
        public void MLBD_HEWU(object sender, MouseButtonEventArgs e)
        {
            // Start by getting the mouse position
            Point pos = e.GetPosition(m_canvas);

            // 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;

            // If there's not an endpoint:
            // 1. Create and attach an incoming heat stream. Position the source endpoint just
            //    below the process unit
            // 2. Create an undo that will remove both
            // 3. Switch to the appropriate state for moving the source endpoint
            if (null == endpoint)
            {
                // Create the actual process unit
                AbstractProcessUnit apu = (AbstractProcessUnit)Activator.CreateInstance(
                    m_type, AbstractProcessUnit.GetNextUID());
                apu.Location = new MathCore.Vector(pos.X, pos.Y);

                HeatStream s = new HeatStream();
                apu.AttachIncomingStream(s);
                s.Destination     = apu;
                s.PropertiesTable = new StreamPropertiesTable(s);

                // Position the source of the heat stream. It's above the process unit by default, unless
                // that would make it go off the screen
                if (apu.Location.Y < 150.0)
                {
                    s.SourceLocation = new MathCore.Vector(
                        apu.Location.X - 10.0, apu.Location.Y + 80.0);
                    s.PropertiesTable.Location = new MathCore.Vector(
                        apu.Location.X + 10.0, apu.Location.Y + 140.0);
                }
                else
                {
                    s.SourceLocation = new MathCore.Vector(
                        apu.Location.X - 10.0, apu.Location.Y - 80.0);
                    s.PropertiesTable.Location = new MathCore.Vector(
                        apu.Location.X + 10.0, apu.Location.Y - 100.0);
                }

                // Add the stream and the process unit to the workspace. Event handlers will update
                // the UI appropriately.
                m_workspace.AddProcessUnit(apu);
                m_workspace.AddStream(s);

                m_workspace.AddUndo(new UndoRedoCollection("Undo creation of heat exchanger with utility",
                                                           new Logic.Undos.DetachIncomingStream(apu, s),
                                                           new Logic.Undos.SetStreamDestination(s, null, apu, s.DestinationLocation),
                                                           new Logic.Undos.RemoveStream(s),
                                                           new Logic.Undos.RemoveProcessUnit(apu)));

                // Select nothing on the canvas
                m_canvas.SelectedElement = null;

                m_palette.SwitchToSelect();

                return;
            }

            // Otherwise, if we HAVE clicked on an endpoint, just deny it by doing nothing
        }
コード例 #18
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();
        }
コード例 #19
0
 public SetProcessUnitLabel(AbstractProcessUnit unit, string labelToSetOnExecution)
 {
     m_lpu   = unit;
     m_label = labelToSetOnExecution;
 }
コード例 #20
0
ファイル: RemoveProcessUnit.cs プロジェクト: petlyuk/CHEMPROV
 public RemoveProcessUnit(AbstractProcessUnit unitToRemove)
 {
     m_remove = unitToRemove;
 }
コード例 #21
0
 public SetProcessUnitLocation(AbstractProcessUnit processUnit, MathCore.Vector location)
 {
     m_apu      = processUnit;
     m_location = location;
 }
コード例 #22
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);
        }
コード例 #23
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);
                }
            }
        }
コード例 #24
0
        /// <summary>
        /// Refreshes the control palette with appropriate controls based on the difficulty setting. This
        /// must be called each time the user changes the difficulty setting in the application.
        /// </summary>
        public void RefreshPalette(OptionDifficultySetting setting)
        {
            // Show or hide the heat stream button based on the setting
            if ((new HeatStream(-1)).IsAvailableWithDifficulty(setting))
            {
                HeatStreamButton.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                HeatStreamButton.Visibility = System.Windows.Visibility.Collapsed;
            }

            // Now we use reflection to create the process unit buttons

            // First clear the content in the process unit stack panel
            ProcessUnitsPanel.Children.Clear();

            // We will create potentially multiple stack panels for rows of buttons
            StackPanel spPUs = null;

            // Keep track of how many buttons we create
            int puBtns = 0;

            // Use reflection to find appropriate process units and streams for the palette
            Assembly a = typeof(Logic.AbstractProcessUnit).Assembly;

            foreach (Type t in a.GetTypes())
            {
                // Ignore abstract types
                if (t.IsAbstract)
                {
                    continue;
                }

                // We only are interested in types that inherit from AbstractProcessUnit
                if (t.IsSubclassOf(typeof(AbstractProcessUnit)) && !t.IsAbstract)
                {
                    // We've found a potential process unit, but we need to make sure that
                    // it can be created under the specified difficulty setting
                    AbstractProcessUnit unit =
                        Activator.CreateInstance(t, (int)-1) as AbstractProcessUnit;
                    if (unit.IsAvailableWithDifficulty(setting))
                    {
                        if (0 == (puBtns % m_buttonsPerRow))
                        {
                            // Create a new row
                            spPUs             = new StackPanel();
                            spPUs.Orientation = Orientation.Horizontal;

                            // Add the first button to it
                            spPUs.Children.Add(CreateButton(
                                                   ProcessUnitControl.GetIconSource(t), unit.Description, t));

                            ProcessUnitsPanel.Children.Add(spPUs);
                        }
                        else
                        {
                            spPUs.Children.Add(CreateButton(
                                                   ProcessUnitControl.GetIconSource(t), unit.Description, t));
                        }

                        puBtns++;
                    }
                }
            }
        }
コード例 #25
0
ファイル: Tests.cs プロジェクト: petlyuk/CHEMPROV
        public void TestCommentMerge()
        {
            // Build a workspace with 2 process units
            Workspace           ws1  = new Workspace();
            AbstractProcessUnit apu1 = new Separator();
            AbstractProcessUnit apu2 = new Separator();

            ws1.AddProcessUnit(apu1);
            ws1.AddProcessUnit(apu2);

            // Add 2 comments to the first and 3 to the second. These will be comments shared
            // between the two workspaces
            apu1.Comments.Add(new StickyNote()
            {
                Text = "Comment 1 on APU1"
            });
            apu1.Comments.Add(new StickyNote()
            {
                Text = "Comment 2 on APU1"
            });
            apu2.Comments.Add(new StickyNote()
            {
                Text = "Comment 1 on APU2"
            });
            apu2.Comments.Add(new StickyNote()
            {
                Text = "Comment 2 on APU2"
            });
            apu2.Comments.Add(new StickyNote()
            {
                Text = "Comment 3 on APU2"
            });

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

            ws1.Save(ms1);

            // Load to a new workspace. The two workspaces should have identical content after
            // the load.
            Workspace ws2 = new Workspace();

            ws2.Load(ms1);

            // Get the process units from the second workspace
            AbstractProcessUnit ws2_apu1 = ws2.GetProcessUnit(apu1.Id);
            AbstractProcessUnit ws2_apu2 = ws2.GetProcessUnit(apu2.Id);

            // Make sure that they both exist
            if (null == ws2_apu1 || null == ws2_apu2)
            {
                Assert.Fail("After save, one or more process units was not found (TestCommentMerge)");
                return;
            }

            // Now is where we add comments that are unique to the different workspaces
            apu1.Comments.Add(new StickyNote()
            {
                Text = "Comment on APU1 only in WS1"
            });
            apu2.Comments.Add(new StickyNote()
            {
                Text = "Comment on APU2 only in WS1"
            });
            ws2_apu1.Comments.Add(new StickyNote()
            {
                Text = "Comment on APU1 only in WS2"
            });
            ws2_apu2.Comments.Add(new StickyNote()
            {
                Text = "Comment on APU2 only in WS2"
            });
            ws2_apu2.Comments.Add(new StickyNote()
            {
                Text = "Another comment on APU2 only in WS2"
            });

            // (Re-)create the memory streams and save both workspaces
            ms1 = new MemoryStream();
            MemoryStream ms2 = new MemoryStream();

            ws1.Save(ms1);
            ws2.Save(ms2);

            // Allocate a third memory stream for the merge
            MemoryStream msMerged = new MemoryStream();

            // Merge
            Core.CommentMerger.Merge(ms1, "WS1_User", ms2, "WS2_User", msMerged);

            // Load back into a workspace and verify
            ws1.Load(msMerged);

            // ------ VERIFICATION ------

            // There should be 2 process units
            apu1 = ws1.GetProcessUnit(apu1.Id);
            apu2 = ws1.GetProcessUnit(apu2.Id);
            if (null == ws2_apu1 || null == ws2_apu2)
            {
                Assert.Fail("After comment merge, one or more process units was not found (TestCommentMerge)");
                return;
            }

            // The first one should have 4 comments. 2 from the original two that are in both documents, 1
            // unique to the first workspace and 1 unique to the second
            Assert.IsTrue(4 == apu1.Comments.Count,
                          "Process unit APU1 in document after merge should have 4 comments but has " +
                          apu1.Comments.Count.ToString());

            // The second one should have 6 comments. 3 from the original two that are in both documents, 1
            // unique to the first workspace and 2 unique to the second
            Assert.IsTrue(6 == apu2.Comments.Count,
                          "Process unit APU2 in document after merge should have 5 comments but has " +
                          apu2.Comments.Count.ToString());
        }
コード例 #26
0
 public DetachIncomingStream(AbstractProcessUnit processUnit, AbstractStream incomingStream)
 {
     m_pu     = processUnit;
     m_stream = incomingStream;
 }
コード例 #27
0
ファイル: Tests.cs プロジェクト: petlyuk/CHEMPROV
        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");
            }
        }