예제 #1
0
      /// <summary>Recomputes the diagram layout based on the current settings.</summary>
      public void Layout() {
         if (IsEmpty || IsAnimating) return;

         // define the visible nodes
         var visibleNodes = new HashSet<BplClass>();
         Func<BplClass, bool> isVisible = c => visibleNodes.Contains(c);
         foreach (var node in Nodes) {
            var bplClass = node.Class;
            if (ClassFilter(bplClass)) {
               node.ComputedVisibility = Visibility.Visible;
               visibleNodes.Add(bplClass);
            } else {
               node.ComputedVisibility = Visibility.Hidden;
            }
         }

         // define the visible blocks
         var isClustered = _check(DisplayOptions.GroupByNamespace) && (_check(LayoutMethod.Hierarchic) || _check(LayoutMethod.Spring));
         foreach (var block in Blocks) {
            if (isClustered && block.Namespace.Classes.Any(c => isVisible(c))) {
               block.ComputedVisibility = Visibility.Visible;
            } else {
               block.ComputedVisibility = Visibility.Hidden;
            }
         }

         // define the visible edges
         Edges.Clear();
         EdgesLayer.Children.Clear();
         SkeletonLayer.Children.Clear();
         var visibleEdges = new List<DiagramEdgeInfo>();

         Action<Func<BplProperty, bool>, DiagramEdgeRole, int> addEdges = (selector, role, weight) => {
            foreach (var source in visibleNodes) {
               var parentIsVisible = source.BaseClass != null && isVisible(source.BaseClass);
               var properties = (parentIsVisible ? source.OwnProperties : source.Properties);
               if (source.Operation != null && source.Operation.Output != null) {
                  if (parentIsVisible) {
                     properties = properties.Union(source.Operation.Output.OwnProperties);
                  } else {
                     properties = properties.Union(source.Operation.Output.Properties);
                  }
               }
               foreach (var property in properties.Where(selector)) {
                  var target = property.ReferencedClass;
                  if (isVisible(target)) {
                     visibleEdges.Add(new DiagramEdgeInfo {
                        Label = property.Name,
                        Role = role | (property.IsCollection || property.IsArray ? DiagramEdgeRole.ZeroToMany : DiagramEdgeRole.ZeroToOne),
                        Source = Nodes[source],
                        Target = Nodes[target],
                        Weight = weight
                     });
                  }
               }
            }
         };

         if (visibleNodes.Count > 0) {

            // define the inheritance edges
            if (_check(DisplayOptions.ShowInheritance)) {
               foreach (var target in visibleNodes) {
                  var source = target.BaseClass;
                  while (source != null && !isVisible(source)) source = source.BaseClass;
                  if (source != null) {
                     visibleEdges.Add(new DiagramEdgeInfo {
                        Role = DiagramEdgeRole.Inheritance,
                        Source = Nodes[source],
                        Target = Nodes[target],
                        Weight = 10
                     });
                  }
               }
            }

            // define the containement edges
            if (_check(DisplayOptions.ShowContainment)) {
               addEdges(prop => prop.IsContainer, DiagramEdgeRole.Containment, 5);
            }

            // define the strong association edges
            if (_check(DisplayOptions.ShowAssociations)) {
               addEdges(prop => prop.IsAssociation, DiagramEdgeRole.Association, 1);
            }

            // define the weak association edges
            if (_check(DisplayOptions.ShowAssociations)) {
               addEdges(prop => prop.IsWeakAssociation, DiagramEdgeRole.WeakAssociation, 1);
            }

            // define the collaboration edges
            if (_check(DisplayOptions.ShowCollaborations)) {
               foreach (var bplClass in visibleNodes.Where(c => !c.Collaborations.IsEmpty)) {
                  foreach (var tuple in bplClass.Collaborations.Where(tuple => isVisible(tuple.Value))) {
                     visibleEdges.Add(new DiagramEdgeInfo {
                        Label = tuple.Key,
                        Role = DiagramEdgeRole.WeakAssociation | DiagramEdgeRole.ZeroToMany,
                        Source = Nodes[bplClass],
                        Target = Nodes[tuple.Value],
                        Weight = 1
                     });
                  }
               }
            }

            // define the association edges between service operations and failures
            if (_check(DisplayOptions.ShowCollaborations)) {
               foreach (var bplClass in visibleNodes.Where(c => c.Operation != null && c.Operation.Failures != null)) {
                  foreach (var failure in bplClass.Operation.Failures.Where(f => isVisible(f))) {
                     visibleEdges.Add(new DiagramEdgeInfo {
                        Label = "Failure",
                        Role = DiagramEdgeRole.WeakAssociation | DiagramEdgeRole.ZeroToMany,
                        Source = Nodes[bplClass],
                        Target = Nodes[failure],
                        Weight = 1
                     });
                  }
               }
            }

         }

         // hide disconnected nodes
         if (_check(DisplayOptions.HideDisconnected)) {
            var connected = new HashSet<DiagramNode>();
            foreach (var edge in visibleEdges) {
               connected.Add(edge.Source);
               connected.Add(edge.Target);
            }
            if (connected.Count > 0) {
               foreach (var node in Nodes.Except(connected)) {
                  node.ComputedVisibility = Visibility.Hidden;
               }
            }
         }

         // layout the diagram
         var oldSize = ComputedSize;
         DiagramLayout.ComputeLayout(this, visibleEdges, isClustered);

         if (_isFirstLayout || _suspendAnimations || AnimationSpeed.TotalMilliseconds < 20) {
            ContentBounds.Width = ComputedSize.Width;
            ContentBounds.Height = ComputedSize.Height;
            Width = ComputedSize.Width;
            Height = ComputedSize.Height;
            Blocks.Apply(b => b.LayoutChanged());
            Nodes.Apply(n => n.LayoutChanged());
            Edges.Apply(e => e.Draw(this));
            _isFirstLayout = false;
            _suspendAnimations = false;
            HideAdorners();
         } else {
            var skeleton = new DiagramSkeleton(Edges);
            SkeletonLayer.Children.Add(skeleton);

            var prototype = new EffectData { Duration = AnimationSpeed, Interpolator = Interpolators.CubicOut };
            var timeline = new ParallelEffect();
            timeline.Add(new ResizeEffect(prototype) { Target = this, From = oldSize, To = ComputedSize });
            timeline.Add(new ResizeEffect(prototype) { Target = ContentBounds, From = oldSize, To = ComputedSize });
            timeline.Add(new NumericEffect(prototype) { Target = skeleton, Property=DiagramSkeleton.StrobeProperty, From = 0.0, To = 1.0});
            Nodes.Apply(n => n.ApplyLayoutEffect(timeline, prototype));
            Blocks.Apply(b => b.LayoutChanged());

            HideAdorners();
            IsAnimating = true;
            timeline.Play(c => {
               SkeletonLayer.Children.Clear();
               Edges.Apply(e => e.Draw(this));
               IsAnimating = false;
               HideAdorners();
            });
         }
      }
예제 #2
0
 /// <summary/>
 protected internal override Effect Decompose() {
    var effect = new ParallelEffect();
    if (FromCenter.CertainlyDifferent(ToCenter)) {
       effect.Add(new CenterShiftEffect(this) {
          From = FromCenter,
          To = ToCenter
       });
    }
    if (FromRotate.CertainlyDifferent(ToRotate)) {
       effect.Add(new RotateEffect(this) {
          From = FromRotate,
          To = ToRotate
       });
    }
    if (FromScale.CertainlyDifferent(ToScale) || FromScaleX.CertainlyDifferent(ToScaleX) || FromScaleY.CertainlyDifferent(ToScaleY)) {
       effect.Add(new ScaleEffect(this) {
          From = FromScale,
          To = ToScale,
          FromScaleX = FromScaleX,
          ToScaleX = ToScaleX,
          FromScaleY = FromScaleY,
          ToScaleY = ToScaleY
       });
    }
    if (FromSkewX.CertainlyDifferent(ToSkewX) || FromSkewY.CertainlyDifferent(ToSkewY)) {
       effect.Add(new SkewEffect(this) {
          FromSkewX = FromSkewX,
          ToSkewX = ToSkewX,
          FromSkewY = FromSkewY,
          ToSkewY = ToSkewY
       });
    }
    if (FromPosition.CertainlyDifferent(ToPosition) || FromX.CertainlyDifferent(ToX) || FromY.CertainlyDifferent(ToY)) {
       effect.Add(new MoveEffect(this) {
          From = FromPosition,
          To = ToPosition,
          FromX = FromX,
          ToX = ToX,
          FromY = FromY,
          ToY = ToY
       });
    }
    if (FromSize.CertainlyDifferent(ToSize) || FromWidth.CertainlyDifferent(ToWidth) || FromHeight.CertainlyDifferent(ToHeight)) {
       effect.Add(new ResizeEffect(this) {
          From = FromSize,
          To = ToSize,
          FromWidth = FromWidth,
          ToWidth = ToWidth,
          FromHeight = FromHeight,
          ToHeight = ToHeight
       });
    }
    return effect;
 }
예제 #3
0
 /// <summary/>
 internal void ApplyLayoutEffect(ParallelEffect timeline, Effect prototype) {
    if (ComputedVisibility != Visibility) {
       Visibility = ComputedVisibility;
       if (Visibility == Visibility.Visible) {
          X = Canvas.ActualWidth / 2;
          Y = Canvas.ActualHeight / 2;
       }
    }
    if (Visibility == Visibility.Visible) {
       timeline.Add(new MoveEffect(prototype) {
          Target = this,
          ToX = ComputedPosition.X,
          ToY = ComputedPosition.Y
       });
    }
 }