public bool IntersectsAnyPU(MathCore.LineSegment segment, params AbstractProcessUnit[] exclusionList) { foreach (UIElement uie in Children) { ProcessUnitControl puc = uie as ProcessUnitControl; if (null == puc) { // Not a process unit control continue; } if (null != exclusionList) { bool goNext = false; foreach (AbstractProcessUnit excludeMe in exclusionList) { // See if we want to exclude this one if (object.ReferenceEquals(puc.ProcessUnit, excludeMe)) { goNext = true; break; } } if (goNext) { continue; } } // Build a rectangle for the control Point pt = new Point( (double)puc.GetValue(Canvas.LeftProperty), (double)puc.GetValue(Canvas.TopProperty)); MathCore.Rectangle r; if (double.IsNaN(puc.Width) || double.IsNaN(puc.Height) || 0.0 == puc.Width || 0.0 == puc.Height) { // Silverlight UI stuff can be funky so we have a condition to use // hard coded dimensions as opposed to getting them from the control r = MathCore.Rectangle.CreateFromCanvasRect(pt, 40.0, 40.0); } else { r = MathCore.Rectangle.CreateFromCanvasRect(pt, puc.Width, puc.Height); } if (r.GetIntersections(segment).Length > 0) { return(true); } } return(false); }
public SubprocessChooserWindow(ProcessUnitControl lpu, Workspace workspace) { InitializeComponent(); // Store a reference to the process unit and workspace m_lpu = lpu; m_workspace = workspace; if (null != lpu) { // Initialize the color options bool didFirst = false; OptionsStackPanel.Children.Clear(); foreach (Core.NamedColor nc in Core.NamedColors.All) { Border b = new Border(); b.BorderBrush = new SolidColorBrush(Colors.LightGray); b.CornerRadius = new CornerRadius(3.0); b.BorderThickness = new Thickness(2.0); b.Background = new SolidColorBrush(nc.Color); if (didFirst) { b.Margin = new Thickness(3.0, 0.0, 3.0, 3.0); } else { b.Margin = new Thickness(3.0); didFirst = true; } // Create the radio button to put in the border RadioButton rb = new RadioButton(); rb.GroupName = "A"; rb.Content = nc.Name; rb.Tag = nc; b.Child = rb; // Setup check-change event rb.Checked += new RoutedEventHandler(rb_Checked); // If the color matches the existing subprocess then check it if (nc.Color.Equals(lpu.Subprocess)) { rb.IsChecked = true; } // Add it to the stack panel OptionsStackPanel.Children.Add(b); } } }
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); }
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); }
/// <summary> /// Callback for when the collection of process units in the workspace changes. We must update /// the UI to match the workspace. /// </summary> private void ProcessUnits_CollectionChanged(object sender, EventArgs e) { // First go through all process unit controls on the canvas and remove ones that are // no longer in the workspace. List <AbstractProcessUnit> unitsThatHaveControls = new List <AbstractProcessUnit>(); for (int i = 0; i < Children.Count; i++) { ProcessUnitControl lpu = Children[i] as ProcessUnitControl; if (null == lpu) { continue; } // Add it to a list that we'll use later unitsThatHaveControls.Add(lpu.ProcessUnit); if (!m_workspace.ProcessUnits.Contains(lpu.ProcessUnit)) { // Tell the process unit to remove itself. It will also remove any // controls used to represent comments. lpu.RemoveSelfFromCanvas(this); // Reset the index since a bunch of child controls could have potentially just // been removed i = -1; } } // Now go through and add any process units that are missing foreach (AbstractProcessUnit apu in m_workspace.ProcessUnits) { if (!unitsThatHaveControls.Contains(apu)) { // Create the process unit. The static method will create it, put it on // the canvas, and take care of all comment sticky notes as well. ProcessUnitControl lpuNew = ProcessUnitControl.CreateOnCanvas(this, apu); } } }
/// <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++; } } } }
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; } } } }
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); } } }