diff --git a/assets/bpmn-js.css b/assets/bpmn-js.css
index ff933e144d..132f25100a 100644
--- a/assets/bpmn-js.css
+++ b/assets/bpmn-js.css
@@ -8,7 +8,7 @@
--color-grey-225-10-80: hsl(225, 10%, 80%);
--color-grey-225-10-85: hsl(225, 10%, 85%);
--color-grey-225-10-90: hsl(225, 10%, 90%);
- --color-grey-225-10-95: hsl(225, 10%, 95%);
+ --color-grey-225-10-95: hsl(225, 10%, 95%);
--color-grey-225-10-97: hsl(225, 10%, 97%);
--color-blue-205-100-45: hsl(205, 100%, 45%);
@@ -24,8 +24,8 @@
--color-red-360-100-97: hsl(360, 100%, 97%);
--color-white: hsl(0, 0%, 100%);
- --color-black: hsl(0, 0%, 0%);
- --color-black-opacity-05: hsla(0, 0%, 0%, 5%);
+ --color-black: hsl(0, 0%, 0%);
+ --color-black-opacity-05: hsla(0, 0%, 0%, 5%);
--color-black-opacity-10: hsla(0, 0%, 0%, 10%);
--breadcrumbs-font-family: var(--bjs-font-family);
@@ -113,4 +113,29 @@
.selected .bjs-drilldown-empty {
display: inherit;
-}
\ No newline at end of file
+}
+
+[data-popup="align-elements"] .djs-popup-body {
+ display: flex;
+}
+
+[data-popup="align-elements"] .djs-popup-body [data-group] + [data-group] {
+ border-left: 1px solid var(--popup-border-color);
+}
+
+[data-popup="align-elements"] [data-group="align"] {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+}
+
+[data-popup="align-elements"] .djs-popup-body .entry {
+ height: 22px;
+ width: 22px;
+
+ padding: 8px 10px;
+}
+
+[data-popup="align-elements"] .djs-popup-body .entry img {
+ height: 100%;
+ width: 100%;
+}
diff --git a/lib/Modeler.js b/lib/Modeler.js
index 717232ba98..7aedb9de40 100644
--- a/lib/Modeler.js
+++ b/lib/Modeler.js
@@ -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';
diff --git a/lib/features/align-elements/AlignElementsContextPadProvider.js b/lib/features/align-elements/AlignElementsContextPadProvider.js
new file mode 100644
index 0000000000..235d053c16
--- /dev/null
+++ b/lib/features/align-elements/AlignElementsContextPadProvider.js
@@ -0,0 +1,87 @@
+import {
+ assign
+} from 'min-dash';
+
+import ICONS from './AlignElementsIcons';
+
+var LOW_PRIORITY = 900;
+
+/**
+ * A provider for align elements context pad button
+ */
+export default function AlignElementsContextPadProvider(contextPad, popupMenu, translate, canvas) {
+
+ contextPad.registerProvider(LOW_PRIORITY, this);
+
+ this._contextPad = contextPad;
+ this._popupMenu = popupMenu;
+ this._translate = translate;
+ this._canvas = canvas;
+}
+
+AlignElementsContextPadProvider.$inject = [
+ 'contextPad',
+ 'popupMenu',
+ 'translate',
+ 'canvas'
+];
+
+AlignElementsContextPadProvider.prototype.getMultiElementContextPadEntries = function(elements) {
+ var actions = {};
+
+ if (this._isAllowed(elements)) {
+ assign(actions, this._getEntries(elements));
+ }
+
+ return actions;
+};
+
+AlignElementsContextPadProvider.prototype._isAllowed = function(elements) {
+ return !this._popupMenu.isEmpty(elements, 'align-elements');
+};
+
+AlignElementsContextPadProvider.prototype._getEntries = function(elements) {
+ var self = this;
+
+ return {
+ 'align-elements': {
+ group: 'align-elements',
+ title: self._translate('Align elements'),
+ imageUrl: ICONS['align'],
+ action: {
+ click: function(event, elements) {
+ var position = self._getMenuPosition(elements);
+
+ assign(position, {
+ cursor: {
+ x: event.x,
+ y: event.y
+ }
+ });
+
+ self._popupMenu.open(elements, 'align-elements', position);
+ }
+ }
+ }
+ };
+};
+
+AlignElementsContextPadProvider.prototype._getMenuPosition = function(elements) {
+ var Y_OFFSET = 5;
+
+ var diagramContainer = this._canvas.getContainer(),
+ pad = this._contextPad.getPad(elements).html;
+
+ var diagramRect = diagramContainer.getBoundingClientRect(),
+ padRect = pad.getBoundingClientRect();
+
+ var top = padRect.top - diagramRect.top;
+ var left = padRect.left - diagramRect.left;
+
+ var pos = {
+ x: left,
+ y: top + padRect.height + Y_OFFSET
+ };
+
+ return pos;
+};
diff --git a/lib/features/align-elements/AlignElementsIcons.js b/lib/features/align-elements/AlignElementsIcons.js
new file mode 100644
index 0000000000..899eca359e
--- /dev/null
+++ b/lib/features/align-elements/AlignElementsIcons.js
@@ -0,0 +1,15 @@
+/**
+ * To change the icons, call `encodeURIComponent` with modified SVG,
+ * and add `data:image/svg+xml;utf8,` in the beginning of the string.
+ */
+var icons = {
+ align: 'data:image/svg+xml;utf8,%3Csvg%20height%3D%222048%22%20width%3D%222048%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M292%204v2044%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M1752%20515H584V77h1168zm-438%20730H584V807h730zm438%20730H584v-438h1168z%22%2F%3E%3C%2Fsvg%3E',
+ bottom: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%222048%22%20height%3D%222048%22%3E%3Cpath%20d%3D%22M0%20442v1314h2044V442h-584v1168h-146V880H730v730H584V442H0zm146%20146h292v1022H146V588zm1460%200h292v1022h-292V588zm-730%20438h292v584H876v-584z%22%20style%3D%22color%3A%23000%3Bfont-style%3Anormal%3Bfont-variant%3Anormal%3Bfont-weight%3A400%3Bfont-stretch%3Anormal%3Bfont-size%3Amedium%3Bline-height%3Anormal%3Bfont-family%3Asans-serif%3Btext-indent%3A0%3Btext-align%3Astart%3Btext-decoration%3Anone%3Btext-decoration-line%3Anone%3Btext-decoration-style%3Asolid%3Btext-decoration-color%3A%23000%3Bletter-spacing%3Anormal%3Bword-spacing%3Anormal%3Btext-transform%3Anone%3Bdirection%3Altr%3Bblock-progression%3Atb%3Bwriting-mode%3Alr-tb%3Bbaseline-shift%3Abaseline%3Btext-anchor%3Astart%3Bwhite-space%3Anormal%3Bclip-rule%3Anonzero%3Bdisplay%3Ainline%3Boverflow%3Avisible%3Bvisibility%3Avisible%3Bopacity%3A1%3Bisolation%3Aauto%3Bmix-blend-mode%3Anormal%3Bcolor-interpolation%3AsRGB%3Bcolor-interpolation-filters%3AlinearRGB%3Bsolid-color%3A%23000%3Bsolid-opacity%3A1%3Bfill%3A%23282828%3Bfill-opacity%3A1%3Bfill-rule%3Aevenodd%3Bstroke%3Anone%3Bstroke-width%3A146.00001526%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%3Bcolor-rendering%3Aauto%3Bimage-rendering%3Aauto%3Bshape-rendering%3Aauto%3Btext-rendering%3Aauto%3Benable-background%3Aaccumulate%22%2F%3E%3C%2Fsvg%3E',
+ center: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20d%3D%22M1027.973%201318v146%22%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M365%20515h1314V77H365v438zM657%201245h730V807H657v438z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M1022%20588v146%22%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M365%201975h1314v-438H365v438z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%2F%3E%3C%2Fsvg%3E',
+ left: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146.00001526%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M0%201537h2044%22%20transform%3D%22rotate(90%20949%20953)%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M511%20369v1168H73V369h438zM1241%20807v730H803V807h438zM1971%20369v1168h-438V369h438z%22%20transform%3D%22rotate(90%20949%20953)%22%2F%3E%3C%2Fsvg%3E',
+ right: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20d%3D%22M1679%204v2044%22%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146.00001526%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M511%20515h1168V77H511v438zM949%201245h730V807H949v438zM511%201975h1168v-438H511v438z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%2F%3E%3C%2Fsvg%3E',
+ top: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146.00001526%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M0%201537h2044%22%20transform%3D%22matrix(1%200%200%20-1%200%201906)%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M511%20369v1168H73V369h438zM1241%20807v730H803V807h438zM1971%20369v1168h-438V369h438z%22%20transform%3D%22matrix(1%200%200%20-1%200%201906)%22%2F%3E%3C%2Fsvg%3E',
+ middle: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M1027.973%201318v146%22%20transform%3D%22rotate(90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M365%20515h1314V77H365v438zM657%201245h730V807H657v438z%22%20transform%3D%22rotate(90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M1022%20588v146%22%20transform%3D%22rotate(90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M365%201975h1314v-438H365v438z%22%20transform%3D%22rotate(90%201022%201026)%22%2F%3E%3C%2Fsvg%3E'
+};
+
+export default icons;
diff --git a/lib/features/align-elements/AlignElementsMenuProvider.js b/lib/features/align-elements/AlignElementsMenuProvider.js
new file mode 100644
index 0000000000..7bb9ced000
--- /dev/null
+++ b/lib/features/align-elements/AlignElementsMenuProvider.js
@@ -0,0 +1,70 @@
+import ICONS from './AlignElementsIcons';
+
+import {
+ assign,
+ forEach,
+} from 'min-dash';
+
+var ALIGNMENT_OPTIONS = [
+ 'left',
+ 'center',
+ 'right',
+ 'top',
+ 'middle',
+ 'bottom'
+];
+
+/**
+ * A provider for align elements popup menu.
+ */
+export default function AlignElementsMenuProvider(popupMenu, alignElements, translate) {
+
+ this._alignElements = alignElements;
+ this._translate = translate;
+ this._popupMenu = popupMenu;
+
+ popupMenu.registerProvider('align-elements', this);
+}
+
+AlignElementsMenuProvider.$inject = [
+ 'popupMenu',
+ 'alignElements',
+ 'translate'
+];
+
+AlignElementsMenuProvider.prototype.getPopupMenuEntries = function(elements) {
+ var entries = {};
+
+ if (this._isAllowed(elements)) {
+ assign(entries, this._getEntries(elements));
+ }
+
+ return entries;
+};
+
+AlignElementsMenuProvider.prototype._isAllowed = function(elements) {
+ return true;
+};
+
+AlignElementsMenuProvider.prototype._getEntries = function(elements) {
+ var alignElements = this._alignElements,
+ translate = this._translate,
+ popupMenu = this._popupMenu;
+
+ var entries = {};
+
+ forEach(ALIGNMENT_OPTIONS, function(alignment) {
+ entries[ 'align-elements-' + alignment ] = {
+ group: 'align',
+ title: translate('Align elements ' + alignment),
+ className: 'bjs-align-elements-menu-entry',
+ imageUrl: ICONS[alignment],
+ action: function(event, entry) {
+ alignElements.trigger(elements, alignment);
+ popupMenu.close();
+ }
+ };
+ });
+
+ return entries;
+};
diff --git a/lib/features/align-elements/index.js b/lib/features/align-elements/index.js
new file mode 100644
index 0000000000..5dcf157e54
--- /dev/null
+++ b/lib/features/align-elements/index.js
@@ -0,0 +1,18 @@
+import AlignElementsModule from 'diagram-js/lib/features/align-elements';
+import ContextPadModule from 'diagram-js/lib/features/context-pad';
+
+import AlignElementsContextPadProvider from './AlignElementsContextPadProvider';
+import AlignElementsMenuProvider from './AlignElementsMenuProvider';
+
+export default {
+ __depends__: [
+ AlignElementsModule,
+ ContextPadModule
+ ],
+ __init__: [
+ 'alignElementsContextPadProvider',
+ 'alignElementsMenuProvider'
+ ],
+ alignElementsContextPadProvider: [ 'type', AlignElementsContextPadProvider ],
+ alignElementsMenuProvider: [ 'type', AlignElementsMenuProvider ]
+};
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-bottom-tool.svg b/lib/features/align-elements/resources/align-bottom-tool.svg
new file mode 100644
index 0000000000..d313c50b90
--- /dev/null
+++ b/lib/features/align-elements/resources/align-bottom-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-horizontal-center-tool.svg b/lib/features/align-elements/resources/align-horizontal-center-tool.svg
new file mode 100644
index 0000000000..7b8aed2a92
--- /dev/null
+++ b/lib/features/align-elements/resources/align-horizontal-center-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-left-tool.svg b/lib/features/align-elements/resources/align-left-tool.svg
new file mode 100644
index 0000000000..6b81bb7bfa
--- /dev/null
+++ b/lib/features/align-elements/resources/align-left-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-right-tool.svg b/lib/features/align-elements/resources/align-right-tool.svg
new file mode 100644
index 0000000000..256faad3f4
--- /dev/null
+++ b/lib/features/align-elements/resources/align-right-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-tool.svg b/lib/features/align-elements/resources/align-tool.svg
new file mode 100644
index 0000000000..808af80768
--- /dev/null
+++ b/lib/features/align-elements/resources/align-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-top-tool.svg b/lib/features/align-elements/resources/align-top-tool.svg
new file mode 100644
index 0000000000..310883dcfb
--- /dev/null
+++ b/lib/features/align-elements/resources/align-top-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/align-elements/resources/align-vertical-center-tool.svg b/lib/features/align-elements/resources/align-vertical-center-tool.svg
new file mode 100644
index 0000000000..f499030038
--- /dev/null
+++ b/lib/features/align-elements/resources/align-vertical-center-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/distribute-elements/DistributeElementsIcons.js b/lib/features/distribute-elements/DistributeElementsIcons.js
new file mode 100644
index 0000000000..774d9ebbf2
--- /dev/null
+++ b/lib/features/distribute-elements/DistributeElementsIcons.js
@@ -0,0 +1,10 @@
+/**
+ * To change the icons, call `encodeURIComponent` with modified SVG,
+ * and add `data:image/svg+xml;utf8,` in the beginning of the string.
+ */
+var icons = {
+ horizontal: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20d%3D%22M73%20661v1022h438V661H73z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M438%20369h1168%22%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M803%20661v730h438V661H803zM1533%20661v1022h438V661h-438z%22%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%2F%3E%3Cpath%20d%3D%22M511%20442v146M1022%20442v146M1533%20442v146%22%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%2F%3E%3C%2Fsvg%3E',
+ vertical: 'data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%222048%22%20width%3D%222048%22%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M73%20661v1022h438V661H73z%22%20transform%3D%22rotate(-90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M438%20369h1168%22%20transform%3D%22rotate(-90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3A%23fff%3Bfill-opacity%3A1%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M803%20661v730h438V661H803zM1533%20661v1022h438V661h-438z%22%20transform%3D%22rotate(-90%201022%201026)%22%2F%3E%3Cpath%20style%3D%22fill%3Anone%3Bfill-rule%3Aevenodd%3Bstroke%3A%23282828%3Bstroke-width%3A146%3Bstroke-linecap%3Abutt%3Bstroke-linejoin%3Amiter%3Bstroke-miterlimit%3A4%3Bstroke-dasharray%3Anone%3Bstroke-dashoffset%3A0%3Bstroke-opacity%3A1%22%20d%3D%22M511%20442v146M1022%20442v146M1533%20442v146%22%20transform%3D%22rotate(-90%201022%201026)%22%2F%3E%3C%2Fsvg%3E',
+};
+
+export default icons;
diff --git a/lib/features/distribute-elements/DistributeElementsMenuProvider.js b/lib/features/distribute-elements/DistributeElementsMenuProvider.js
new file mode 100644
index 0000000000..a8ae7feb41
--- /dev/null
+++ b/lib/features/distribute-elements/DistributeElementsMenuProvider.js
@@ -0,0 +1,67 @@
+import ICONS from './DistributeElementsIcons';
+
+import { assign } from 'min-dash';
+
+var LOW_PRIORITY = 900;
+
+/**
+ * A provider for distribute elements popup menu.
+ */
+export default function DistributeElementsMenuProvider(popupMenu, distributeElements, translate) {
+ this._distributeElements = distributeElements;
+ this._translate = translate;
+ this._popupMenu = popupMenu;
+
+ popupMenu.registerProvider('align-elements', LOW_PRIORITY, this);
+}
+
+DistributeElementsMenuProvider.$inject = [
+ 'popupMenu',
+ 'distributeElements',
+ 'translate'
+];
+
+DistributeElementsMenuProvider.prototype.getPopupMenuEntries = function(elements) {
+ var entries = {};
+
+ if (this._isAllowed(elements)) {
+ assign(entries, this._getEntries(elements));
+ }
+
+ return entries;
+};
+
+DistributeElementsMenuProvider.prototype._isAllowed = function(elements) {
+ return true;
+};
+
+DistributeElementsMenuProvider.prototype._getEntries = function(elements) {
+ var distributeElements = this._distributeElements,
+ translate = this._translate,
+ popupMenu = this._popupMenu;
+
+ var entries = {
+ 'distribute-elements-horizontally': {
+ group: 'distribute',
+ title: translate('Distribute elements horizontally'),
+ className: 'bjs-align-elements-menu-entry',
+ imageUrl: ICONS['horizontal'],
+ action: function(event, entry) {
+ distributeElements.trigger(elements, 'horizontal');
+ popupMenu.close();
+ }
+ },
+ 'distribute-elements-vertically': {
+ group: 'distribute',
+ title: translate('Distribute elements vertically'),
+ className: 'bjs-align-elements-menu-entry',
+ imageUrl: ICONS['vertical'],
+ action: function(event, entry) {
+ distributeElements.trigger(elements, 'vertical');
+ popupMenu.close();
+ }
+ },
+ };
+
+ return entries;
+};
diff --git a/lib/features/distribute-elements/index.js b/lib/features/distribute-elements/index.js
index d6ec22c8dc..15ea2f0ff6 100644
--- a/lib/features/distribute-elements/index.js
+++ b/lib/features/distribute-elements/index.js
@@ -1,12 +1,19 @@
import DistributeElementsModule from 'diagram-js/lib/features/distribute-elements';
+import PopupMenuModule from 'diagram-js/lib/features/popup-menu';
import BpmnDistributeElements from './BpmnDistributeElements';
+import DistributeElementsMenuProvider from './DistributeElementsMenuProvider';
export default {
__depends__: [
+ PopupMenuModule,
DistributeElementsModule
],
- __init__: [ 'bpmnDistributeElements' ],
- bpmnDistributeElements: [ 'type', BpmnDistributeElements ]
+ __init__: [
+ 'bpmnDistributeElements',
+ 'distributeElementsMenuProvider'
+ ],
+ bpmnDistributeElements: [ 'type', BpmnDistributeElements ],
+ distributeElementsMenuProvider: [ 'type', DistributeElementsMenuProvider ]
};
diff --git a/lib/features/distribute-elements/resources/distribute-horizontally-tool.svg b/lib/features/distribute-elements/resources/distribute-horizontally-tool.svg
new file mode 100644
index 0000000000..6ded9bfa04
--- /dev/null
+++ b/lib/features/distribute-elements/resources/distribute-horizontally-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/features/distribute-elements/resources/distribute-vertically-tool.svg b/lib/features/distribute-elements/resources/distribute-vertically-tool.svg
new file mode 100644
index 0000000000..f2c8c5ff73
--- /dev/null
+++ b/lib/features/distribute-elements/resources/distribute-vertically-tool.svg
@@ -0,0 +1 @@
+
\ No newline at end of file