Skip to content

Commit

Permalink
feat: add alignment buttons for multi-element context pad
Browse files Browse the repository at this point in the history
Related to #1680
  • Loading branch information
barmac committed Jun 10, 2022
1 parent 19eefcc commit 709066a
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 41 deletions.
2 changes: 1 addition & 1 deletion lib/Modeler.js
Expand Up @@ -10,7 +10,7 @@ import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
import TouchModule from 'diagram-js/lib/navigation/touch';
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';

import AlignElementsModule from 'diagram-js/lib/features/align-elements';
import AlignElementsModule from './features/align-elements';
import AutoPlaceModule from './features/auto-place';
import AutoResizeModule from './features/auto-resize';
import AutoScrollModule from 'diagram-js/lib/features/auto-scroll';
Expand Down
73 changes: 73 additions & 0 deletions lib/features/align-elements/AlignElementsContextPadProvider.js
@@ -0,0 +1,73 @@
import ICONS from './AlignElementsIcons';

import {
assign,
forEach
} from 'min-dash';

var ALIGNMENT_OPTIONS = [
'left',
'center',
'right',
'top',
'middle',
'bottom'
];

var LOW_PRIORITY = 900;

/**
* A provider for BPMN 2.0 elements context pad
*/
export default function AlignElementsContextPadProvider(contextPad, alignElements, translate) {

contextPad.registerProvider(LOW_PRIORITY, this);

this._contextPad = contextPad;

this._alignElements = alignElements;
this._translate = translate;
}

AlignElementsContextPadProvider.$inject = [
'contextPad',
'alignElements',
'translate'
];

AlignElementsContextPadProvider.prototype.getMultiElementContextPadEntries = function(elements) {
var actions = {};

if (this._isAllowed(elements)) {
assign(actions, this._getEntries(elements));
}

return actions;
};

AlignElementsContextPadProvider.prototype._isAllowed = function(elements) {
return true;
};

AlignElementsContextPadProvider.prototype._getEntries = function(elements) {
var alignElements = this._alignElements,
translate = this._translate;

var entries = {};

forEach(ALIGNMENT_OPTIONS, function(alignment) {
entries['align-elements-' + alignment] = {
group: 'align',
className: 'bjs-align',
title: translate('Align elements ' + alignment),
imageUrl: ICONS[alignment],
action: {
click: function(event, elements) {
alignElements.trigger(elements, alignment);
}
}
};
});

return entries;
};
14 changes: 14 additions & 0 deletions lib/features/align-elements/AlignElementsIcons.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions lib/features/align-elements/index.js
@@ -0,0 +1,13 @@
import AlignElementsModule from 'diagram-js/lib/features/align-elements';
import ContextPadModule from 'diagram-js/lib/features/context-pad';

import AlignElementsContextPadProvider from './AlignElementsContextPadProvider';

export default {
__depends__: [
AlignElementsModule,
ContextPadModule
],
__init__: [ 'alignElementsContextPadProvider' ],
alignElementsContextPadProvider: [ 'type', AlignElementsContextPadProvider ]
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/features/align-elements/resources/align-left-tool.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/features/align-elements/resources/align-right-tool.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/features/align-elements/resources/align-top-tool.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions lib/features/context-pad/ContextPadProvider.js
Expand Up @@ -107,6 +107,10 @@ ContextPadProvider.prototype.getMultiElementContextPadEntries = function(element
});
}

if (this._isDistributionAllowed(elements)) {
assign(actions, this._getDistributionEntries(elements));
}

return actions;
};

Expand All @@ -129,6 +133,14 @@ ContextPadProvider.prototype._isDeleteAllowed = function(elements) {
return baseAllowed;
};

ContextPadProvider.prototype._isDistributionAllowed = function(elements) {
return true;
};

ContextPadProvider.prototype._getDistributionEntries = function(elements) {
return {};
};

ContextPadProvider.prototype.getContextPadEntries = function(element) {
var contextPad = this._contextPad,
modeling = this._modeling,
Expand Down
105 changes: 103 additions & 2 deletions test/spec/features/align-elements/BpmnAlignElementsSpec.js
Expand Up @@ -3,19 +3,113 @@ import {
inject
} from 'test/TestHelper';

import alignElementsModule from 'diagram-js/lib/features/align-elements';
import alignElementsModule from 'lib/features/align-elements';
import modelingModule from 'lib/features/modeling';
import coreModule from 'lib/core';
import contextPadModule from 'lib/features/context-pad';

import {
forEach
} from 'min-dash';

import {
query as domQuery
} from 'min-dom';


describe('features/align-elements', function() {

var testModules = [ alignElementsModule, modelingModule, coreModule ];
var testModules = [ alignElementsModule, modelingModule, coreModule, contextPadModule ];

var basicXML = require('../../../fixtures/bpmn/align-elements.bpmn');

beforeEach(bootstrapModeler(basicXML, { modules: testModules }));


describe('context pad provider', function() {

var alignEntries;

beforeEach(inject(function(contextPad) {
alignEntries = function(target) {
var entries = [];

forEach([
'align-elements-left',
'align-elements-center',
'align-elements-right',
'align-elements-top',
'align-elements-middle',
'align-elements-bottom'
], function(actionName) {
var entry = padEntry(contextPad.getPad(target).html, actionName);

if (entry) {
entries.push(entry);
}
});

return entries;
};
}));


it('should NOT provide alignment entries for single element', inject(
function(elementRegistry, contextPad) {

// given
var task = elementRegistry.get('Task_lane');

// when
contextPad.open(task);

// then
expect(alignEntries(task)).to.have.lengthOf(0);
}
));


it('should provide alignment entries for multiple elements', inject(
function(elementRegistry, contextPad) {

// given
var taskBoundEvt = elementRegistry.get('Task_boundary_evt'),
task = elementRegistry.get('Task_lane'),
subProcess = elementRegistry.get('SubProcess_lane'),
endEvent = elementRegistry.get('EndEvent_lane'),
elements = [ taskBoundEvt, task, subProcess, endEvent ];

// when
contextPad.open(elements);

// then
expect(alignEntries(elements)).to.have.lengthOf(6);
}
));


it('should provide entries after the delete icon', inject(
function(elementRegistry, contextPad) {

// given
var taskBoundEvt = elementRegistry.get('Task_boundary_evt'),
task = elementRegistry.get('Task_lane'),
subProcess = elementRegistry.get('SubProcess_lane'),
endEvent = elementRegistry.get('EndEvent_lane'),
elements = [ taskBoundEvt, task, subProcess, endEvent ];

// when
contextPad.open(elements);

// then
var pad = contextPad.getPad(elements).html;

expect(domQuery('[data-group="edit"] ~ [data-group="align"]', pad)).to.exist;
}
));
});


describe('integration', function() {

it('should align to the left', inject(function(elementRegistry, alignElements) {
Expand Down Expand Up @@ -134,3 +228,10 @@ describe('features/align-elements', function() {
});

});


// helper //////////////////////////////////////////////////////////////////////

function padEntry(element, name) {
return domQuery('[data-action="' + name + '"]', element);
}

0 comments on commit 709066a

Please sign in to comment.