function GridSnapping(elementRegistry, eventBus, config) {

  var active = !config || config.active !== false;

  this._eventBus = eventBus;

  var self = this;

  eventBus.on('diagram.init', LOW_PRIORITY, function() {
    self.setActive(active);
  });

  eventBus.on([
    'create.move',
    'create.end',
    'bendpoint.move.move',
    'bendpoint.move.end',
    'connect.move',
    'connect.end',
    'connectionSegment.move.move',
    'connectionSegment.move.end',
    'resize.move',
    'resize.end',
    'shape.move.move',
    'shape.move.end'
  ], LOWER_PRIORITY, function(event) {
    var originalEvent = event.originalEvent;

    if (!self.active || (originalEvent && isCmd(originalEvent))) {
      return;
    }

    var context = event.context,
        gridSnappingContext = context.gridSnappingContext;

    if (!gridSnappingContext) {
      gridSnappingContext = context.gridSnappingContext = {};
    }

    [ 'x', 'y' ].forEach(function(axis) {
      var options = {};

      // allow snapping with offset
      var snapOffset = getSnapOffset(event, axis, elementRegistry);

      if (snapOffset) {
        options.offset = snapOffset;
      }

      // allow snapping with min and max
      var snapConstraints = getSnapConstraints(event, axis);

      if (snapConstraints) {
        assign(options, snapConstraints);
      }

      if (!isSnapped(event, axis)) {
        self.snapEvent(event, axis, options);
      }
    });
  });
}
Basic grid snapping that covers connecting, creating, moving, resizing shapes, moving bendpoints
and connection segments.

@param {ElementRegistry} elementRegistry
@param {EventBus} eventBus
@param {Object} config