# all files / Github/diagram-js/lib/features/modeling/cmd/helper/ MoveHelper.js

95.83% Statements 23/24
95.24% Branches 20/21
100% Functions 6/6
95.83% Lines 23/24

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99

    2256×

    1×
    183×

    183×

    1×
    589×

    589×
    589×
    589×
    589×
    589×

    589×
    23×

    589×

    651×

    589×

    351×
    351×

    351×
    117×

    234×

    1×
    589×
     import {
      forEach
    } from 'min-dash';

    import {
      getMovedSourceAnchor,
      getMovedTargetAnchor
    } from './AnchorsHelper';

    import MoveClosure from './MoveClosure';

    /**
     * A helper that is able to carry out serialized move
     * operations on multiple elements.
     *
     * @param {Modeling} modeling
     */
    export default function MoveHelper(modeling) {
      this._modeling = modeling;
    }

    /**
     * Move the specified elements and all children by the given delta.
     *
     * This moves all enclosed connections, too and layouts all affected
     * external connections.
     *
     * @param  {Array<djs.model.Base>} elements
     * @param  {Point} delta
     * @param  {djs.model.Base} newParent applied to the first level of shapes
     *
     * @return {Array<djs.model.Base>} list of touched elements
     */
    MoveHelper.prototype.moveRecursive = function(elements, delta, newParent) {
      Iif (!elements) {
        return [];
      } else {
        return this.moveClosure(this.getClosure(elements), delta, newParent);
      }
    };

    /**
     * Move the given closure of elmements.
     *
     * @param {Object} closure
     * @param {Point} delta
     * @param {djs.model.Base} [newParent]
     * @param {djs.model.Base} [newHost]
     */
    MoveHelper.prototype.moveClosure = function(closure, delta, newParent, newHost, primaryShape) {
      var modeling = this._modeling;

      var allShapes = closure.allShapes,
          allConnections = closure.allConnections,
          enclosedConnections = closure.enclosedConnections,
          topLevel = closure.topLevel,
          keepParent = false;

      if (primaryShape && primaryShape.parent === newParent) {
        keepParent = true;
      }

      // move all shapes
      forEach(allShapes, function(shape) {

        // move the element according to the given delta
        modeling.moveShape(shape, delta, topLevel[shape.id] && !keepParent && newParent, {
          recurse: false,
          layout: false
        });
      });

      // move all child connections / layout external connections
      forEach(allConnections, function(c) {

        var sourceMoved = !!allShapes[c.source.id],
            targetMoved = !!allShapes[c.target.id];

        if (enclosedConnections[c.id] && sourceMoved && targetMoved) {
          modeling.moveConnection(c, delta, topLevel[c.id] && !keepParent && newParent);
        } else {
          modeling.layoutConnection(c, {
            connectionStart: sourceMoved && getMovedSourceAnchor(c, c.source, delta),
            connectionEnd: targetMoved && getMovedTargetAnchor(c, c.target, delta)
          });
        }
      });
    };

    /**
     * Returns the closure for the selected elements
     *
     * @param  {Array<djs.model.Base>} elements
     * @return {MoveClosure} closure
     */
    MoveHelper.prototype.getClosure = function(elements) {
      return new MoveClosure().addAll(elements, true);
    };