public StreamTableControl(StreamPropertiesTable tableData,
                                  PFD.Streams.StreamControl parent, Workspace workspace, DrawingCanvas canvas)
        {
            InitializeComponent();

            m_table  = tableData;
            m_parent = parent;
            m_ws     = workspace;
            m_canvas = canvas;

            // Do the initial UI setup
            HeaderTextBlock.Text = "Stream #" + m_table.Stream.Id.ToString();
            Location             = new Point(tableData.Location.X, tableData.Location.Y);
            UpdateUI();

            // Ensure that the minimize button eats mouse events
            MinimizeButton.MouseLeftButtonDown += this.MinimizeButton_MouseButtonEvent;
            MinimizeButton.MouseLeftButtonUp   += this.MinimizeButton_MouseButtonEvent;

            // Monitor changes in the parent stream (all we care about is the Id)
            m_table.Stream.PropertyChanged += this.Stream_PropertyChanged;

            // Monitor changes in the row data
            m_table.RowPropertyChanged += new PropertyChangedEventHandler(RowPropertyChanged);

            m_table.RowsChanged += new EventHandler(TableRowsChanged);

            // Monitor changes to the difficulty level so we can show/hide the temperature row
            // for chemical stream property tables
            m_ws.PropertyChanged += new PropertyChangedEventHandler(WorkspacePropertyChanged);

            // Monitor changes to m_table
            m_table.PropertyChanged += new PropertyChangedEventHandler(TablePropertyChanged);
        }
示例#2
0
        /// <summary>
        /// The member variable m_highlightedHover can be a reference to a process unit with a highlighted
        /// border or a stream with a specially colored stem line. This method removes either of these
        /// highlights and sets the member variable back to null.
        /// </summary>
        private void UnhighlightHover()
        {
            if (null == m_highlightedHover)
            {
                return;
            }

            ProcessUnitControl gpu = m_highlightedHover as ProcessUnitControl;

            if (null != gpu)
            {
                gpu.SetBorderColor(ProcessUnitBorderColor.NoBorder);
            }
            else
            {
                PFD.Streams.StreamControl s = m_highlightedHover as PFD.Streams.StreamControl;
                if (null != s)
                {
                    s.Selected = true;
                    s.Selected = false;
                }
            }

            m_highlightedHover = null;
        }
示例#3
0
        // Refactoring on this method is done (logic-wise, could use some cleanup otherwise)
        private static void DeleteHEWU(ProcessUnitControl he, DrawingCanvas canvas)
        {
            Workspace ws = canvas.GetWorkspace();

            // Heat exchangers with utilities must also delete the heat stream that's incoming
            // Normally the heat stream is at index 0 among the incoming streams, but it seems like
            // this does not always hold true when loading from files so it's just safer to search
            // for it
            HeatStream heatStream = null;

            foreach (AbstractStream incomingStream in he.ProcessUnit.IncomingStreams)
            {
                if (incomingStream is HeatStream)
                {
                    heatStream = incomingStream as HeatStream;
                    break;
                }
            }
            PFD.Streams.StreamControl heatStreamControl =
                canvas.GetStreamControl(heatStream) as PFD.Streams.StreamControl;

            List <IUndoRedoAction> undos = new List <IUndoRedoAction>();

            undos.Add(new Logic.Undos.AddToWorkspace(heatStream));
            undos.Add(new Logic.Undos.AddToWorkspace(he.ProcessUnit));

            // We need to check if the attached stream has a source
            if (null != heatStream.Source)
            {
                // Detach with undo
                undos.Add(new Logic.Undos.AttachOutgoingStream(heatStream.Source, heatStream));
                heatStream.Source.DetachOutgoingStream(heatStream);
            }

            // Detach all outgoing streams and make undos
            foreach (AbstractStream s in he.ProcessUnit.OutgoingStreams)
            {
                undos.Add(new Logic.Undos.SetStreamSource(s, he.ProcessUnit, null,
                                                          s.SourceLocation));
                s.Source = null;
            }

            // Detach all incoming streams and make undos
            foreach (AbstractStream s in he.ProcessUnit.IncomingStreams)
            {
                undos.Add(new Logic.Undos.SetStreamDestination(s, he.ProcessUnit, null,
                                                               s.DestinationLocation));
                s.Destination = null;
            }

            ws.AddUndo(new UndoRedoCollection(
                           "Undo deletion of heat exchanger with utility", undos.ToArray()));

            // Remove the stream and process unit from the workspace. Event handlers will update the UI.
            ws.RemoveStream(heatStream);
            ws.RemoveProcessUnit(he.ProcessUnit);
        }
示例#4
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);
        }
示例#5
0
        public bool IsStreamEndpoint(UIElement element)
        {
            foreach (UIElement uie in Children)
            {
                PFD.Streams.StreamControl s = uie as PFD.Streams.StreamControl;
                if (s != null)
                {
                    if (element == s.SourceDragIcon || element == s.DestinationDragIcon)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#6
0
        private void Streams_CollectionChanged(object sender, EventArgs e)
        {
            // First go through all stream controls on the canvas and remove ones that are
            // no longer in the workspace.
            List <AbstractStream> streamsThatHaveControls =
                new List <AbstractStream>();

            for (int i = 0; i < Children.Count; i++)
            {
                PFD.Streams.StreamControl stream = Children[i] as PFD.Streams.StreamControl;
                if (null == stream)
                {
                    continue;
                }

                // Add it to a list that we'll use later
                streamsThatHaveControls.Add(stream.Stream);

                if (!m_workspace.Streams.Contains(stream.Stream))
                {
                    // Tell the stream control to remove itself and all it's children (stream lines,
                    // comment sticky note controls, etc.)
                    stream.RemoveSelfFromCanvas(this);

                    // Reset the index since a bunch of child controls could have potentially just
                    // been removed
                    i = -1;
                }
            }

            // Now go through and add stream controls that are missing
            foreach (AbstractStream stream in m_workspace.Streams)
            {
                if (!streamsThatHaveControls.Contains(stream))
                {
                    PFD.Streams.StreamControl.CreateOnCanvas(this, stream);
                }
            }
        }
示例#7
0
        private void AddCommentCollectionMenuOptions(ContextMenu newContextMenu, string title)
        {
            // Make the header in the menu for the comment-specific options
            MenuItem menuItem = new MenuItem();

            menuItem.Header = title;
            newContextMenu.Items.Add(menuItem);
            // We're using this item as a label, so don't let the user click it
            menuItem.IsHitTestVisible = false;
            // Change the colors to signal to the user that it's a label
            menuItem.Background = new SolidColorBrush(Colors.LightGray);
            menuItem.Foreground = new SolidColorBrush(Color.FromArgb(255, 100, 100, 100));
            menuItem.FontWeight = FontWeights.Bold;

            menuItem        = new MenuItem();
            menuItem.Header = "Add new comment";
            menuItem.Tag    = m_canvas.SelectedElement;
            newContextMenu.Items.Add(menuItem);

            // Use an anonymous delegate to handle the click event
            menuItem.Click += delegate(object sender, RoutedEventArgs e)
            {
                MenuItem tempMI = sender as MenuItem;
                PFD.Streams.StreamControl stream = tempMI.Tag as PFD.Streams.StreamControl;
                ProcessUnitControl        unit   = tempMI.Tag as ProcessUnitControl;

                // Get a reference to the comment collection
                IList <StickyNote> comments;
                if (null != stream)
                {
                    comments = stream.Stream.Comments;
                }
                else
                {
                    comments = unit.ProcessUnit.Comments;
                }

                // Compute the location for the new comment
                MathCore.Vector location = StickyNoteControl.ComputeNewCommentNoteLocation(
                    m_canvas, tempMI.Tag, 100.0, 100.0);

                // Create the new sticky note and add it to the workspace. Event handlers will update
                // the UI appropriately
                StickyNote sn = new StickyNote()
                {
                    Width     = 100.0,
                    Height    = 100.0,
                    LocationX = location.X,
                    LocationY = location.Y
                };
                comments.Add(sn);

                // Add an undo that will remove the comment
                m_workspace.AddUndo(new UndoRedoCollection("Undo creation of comment",
                                                           new RemoveComment(comments, comments.IndexOf(sn))));

                // Make sure to remove the popup menu from the canvas
                m_canvas.Children.Remove(m_contextMenu);
                m_contextMenu = null;

                // Flip back to the default state for the canvas (null)
                m_canvas.CurrentState = null;
            };

            string objName = "selected object";

            if (m_canvas.SelectedElement is ProcessUnitControl)
            {
                objName = (m_canvas.SelectedElement as ProcessUnitControl).ProcessUnit.Label;
            }
            else if (m_canvas.SelectedElement is ChemProV.PFD.Streams.StreamControl)
            {
                objName = "selected stream";
            }

            // Add a new menu item to hide all comments
            menuItem        = new MenuItem();
            menuItem.Header = "Hide all comments for " + objName;
            menuItem.Tag    = m_canvas.SelectedElement;
            newContextMenu.Items.Add(menuItem);
            menuItem.Click += delegate(object sender, RoutedEventArgs e)
            {
                MenuItem tempMI = sender as MenuItem;
                (tempMI.Tag as UI.ICommentControlManager).HideAllComments();

                // Make sure to remove the popup menu from the canvas
                m_canvas.Children.Remove(m_contextMenu);
                m_contextMenu = null;

                // Flip back to the default state for the canvas (null)
                m_canvas.CurrentState = null;
            };

            // Add one to show all comments too
            menuItem        = new MenuItem();
            menuItem.Header = "Show all comments for " + objName;
            menuItem.Tag    = m_canvas.SelectedElement;
            newContextMenu.Items.Add(menuItem);
            menuItem.Click += delegate(object sender, RoutedEventArgs e)
            {
                MenuItem tempMI = sender as MenuItem;
                (tempMI.Tag as UI.ICommentControlManager).ShowAllComments();

                // Make sure to remove the popup menu from the canvas
                m_canvas.Children.Remove(m_contextMenu);
                m_contextMenu = null;

                // Flip back to the default state for the canvas (null)
                m_canvas.CurrentState = null;
            };
        }
示例#8
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);
        }
示例#9
0
        public static MathCore.Vector ComputeNewCommentNoteLocation(DrawingCanvas canvas, object parentControl,
                                                                    double controlWidth = 100.0, double controlHeight = 100.0)
        {
            // First resolve the "center point" of the parent object. Also get a reference to the collection
            // of comments.
            Point location;
            IList <StickyNote> comments;
            ProcessUnitControl lpu = parentControl as ProcessUnitControl;

            PFD.Streams.StreamControl stream = parentControl as PFD.Streams.StreamControl;
            if (null != lpu)
            {
                location = lpu.Location;
                comments = lpu.ProcessUnit.Comments;
            }
            else if (null != stream)
            {
                location = stream.StreamLineMidpoint;
                comments = stream.Stream.Comments;
            }
            else
            {
                throw new ArgumentException(
                          "Parent control for a comment sticky note must be a stream or process unit " +
                          "control.\n Method: ComputeNewCommentNoteLocation");
            }

            // Get a reference to the workspace. We will look at other sticky notes in this workspace to
            // try to avoid direct overlap.
            Workspace ws = canvas.GetWorkspace();

            MathCore.Vector loc;
            int             attempts = 0;

            while (true)
            {
                // Compute a location
                double radius = 150.0;
                double angle  = (double)(comments.Count % 6) * 60.0 / 180.0 * Math.PI;
                loc = new MathCore.Vector(
                    location.X + radius * Math.Cos(angle),
                    location.Y + radius * Math.Sin(angle));

                // Make sure this location wouldn't make the control go off the canvas
                if (loc.X - (controlWidth / 2.0) < 0.0 ||
                    loc.Y - (controlHeight / 2.0) < 0.0)
                {
                    attempts++;
                }
                else if ((null != stream && stream.Stream.ContainsCommentWithLocation(loc.X, loc.Y)) ||
                         (null != lpu && lpu.ProcessUnit.ContainsCommentWithLocation(loc.X, loc.Y)))
                {
                    attempts++;
                }
                else
                {
                    // This means the location is ok and we can return it
                    return(loc);
                }

                // Try cascading if radial position failed
                if (attempts > 6)
                {
                    // Reset attempts because we're about to try another method of positioning
                    attempts = 0;

                    double offset = 10.0;
                    while (true)
                    {
                        loc.X = location.X + radius + offset;
                        loc.Y = location.Y + offset;

                        // Make sure this location wouldn't make the control go off the canvas
                        if (loc.X - (controlWidth / 2.0) < 0.0 ||
                            loc.Y - (controlHeight / 2.0) < 0.0)
                        {
                            attempts++;
                        }
                        else if ((null != stream && stream.Stream.ContainsCommentWithLocation(loc.X, loc.Y)) ||
                                 (null != lpu && lpu.ProcessUnit.ContainsCommentWithLocation(loc.X, loc.Y)))
                        {
                            attempts++;
                        }
                        else
                        {
                            // This means the location is ok and we can return it
                            return(loc);
                        }

                        attempts++;
                        if (attempts > 50)
                        {
                            // Just give up and choose an arbitrary position
                            return(new MathCore.Vector(location.X + radius, location.Y));
                        }

                        // Increase the offset for the next attempt
                        offset += 10.0;
                    }
                }
            }
        }
示例#10
0
        public UIElement GetChildAtIncludeStreams(Point location, params object[] excludeThese)
        {
            UIElement element = null;

            foreach (UIElement uie in Children)
            {
                // If it's in the exclusion list then ignore it
                if (null != excludeThese)
                {
                    if (Array.IndexOf <object>(excludeThese, uie) >= 0)
                    {
                        continue;
                    }
                }

                // If it's collapsed then ignore it
                if (System.Windows.Visibility.Collapsed == uie.Visibility)
                {
                    continue;
                }

                double w = (double)uie.GetValue(Canvas.ActualWidthProperty);
                double h = (double)uie.GetValue(Canvas.ActualHeightProperty);
                double x = (double)uie.GetValue(Canvas.LeftProperty);
                double y = (double)uie.GetValue(Canvas.TopProperty);

                if (location.X >= x && location.X < x + w &&
                    location.Y >= y && location.Y < y + h)
                {
                    // We found something at this location, but we need to check if we have another element
                    // with a higher Z-index
                    if (null != element)
                    {
                        if ((int)uie.GetValue(Canvas.ZIndexProperty) >= (int)element.GetValue(Canvas.ZIndexProperty))
                        {
                            element = uie;
                        }
                    }
                    else
                    {
                        element = uie;
                    }
                }
            }

            // Check streams if we didn't get anything above
            if (null == element)
            {
                // We'll say any click within 4-pixels distance from the line is close enough
                double dist = 4.0;
                foreach (UIElement uie in Children)
                {
                    // If it's in the exclusion list then ignore it
                    if (null != excludeThese)
                    {
                        if (Array.IndexOf <object>(excludeThese, uie) >= 0)
                        {
                            continue;
                        }
                    }

                    PFD.Streams.StreamControl stream = uie as PFD.Streams.StreamControl;
                    if (null == stream)
                    {
                        continue;
                    }

                    if (stream.GetShortestDistanceFromLines(location) <= dist)
                    {
                        return(stream);
                    }
                }
            }

            return(element);
        }