Skip to content

Commit

Permalink
feat: integrate implicit keyboard binding into BPMN and DMN editors
Browse files Browse the repository at this point in the history
  Related to bpmn-io/internal-docs#1081

feat: expose `canvasFocused` to menu actions

  This allows menu actions in plug-ins to properly react to the newly
  introduced canvas focused state, and make them activate only on
  canvas focus, not _any_ focus.

fix: only trigger core editor keyboard shortcuts on canvas focus
  • Loading branch information
jarekdanielak authored and nikku committed Nov 20, 2024
1 parent 7b129b8 commit fa33f00
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 132 deletions.
51 changes: 24 additions & 27 deletions client/src/app/tabs/bpmn/BpmnEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,6 @@ export class BpmnEditor extends CachedComponent {
'elements.copied',
'propertiesPanel.focusin',
'propertiesPanel.focusout',
'directEditing.activate',
'directEditing.deactivate',
'searchPad.closed',
'searchPad.opened',
'popupMenu.opened',
'popupMenu.closed',
'elementTemplates.select'
].forEach((event) => {
modeler[fn](event, this.handleChanged);
});
Expand Down Expand Up @@ -432,45 +425,46 @@ export class BpmnEditor extends CachedComponent {

const selectionLength = selection.get().length;

const inputActive = isInputActive();
const canvasFocused = modeler.get('canvas').isFocused();

const newState = {
align: selectionLength > 1,
appendElement: !inputActive,
appendElement: canvasFocused,
canvasFocused,
close: true,
copy: !!selectionLength,
cut: false,
createElement: !inputActive,
defaultCopyCutPaste: inputActive,
defaultUndoRedo: inputActive,
createElement: canvasFocused,
defaultCopyCutPaste: !canvasFocused,
defaultUndoRedo: !canvasFocused,
dirty,
distribute: selectionLength > 2,
editLabel: !inputActive && !!selectionLength,
editLabel: canvasFocused && selectionLength === 1,
exportAs: EXPORT_AS,
find: !inputActive,
globalConnectTool: !inputActive,
handTool: !inputActive,
inputActive,
lassoTool: !inputActive,
moveCanvas: !inputActive,
moveToOrigin: !inputActive,
moveSelection: !inputActive && !!selectionLength,
find: canvasFocused,
globalConnectTool: canvasFocused,
handTool: canvasFocused,
lassoTool: canvasFocused,
moveCanvas: canvasFocused,
moveToOrigin: canvasFocused,
moveSelection: canvasFocused && !!selectionLength,
paste: !modeler.get('clipboard').isEmpty(),
platform: 'platform',
propertiesPanel: true,
redo: commandStack.canRedo(),
removeSelected: !!selectionLength || inputActive,
replaceElement: !!selectionLength && selectionLength == 1 && !inputActive,
redo: canvasFocused && commandStack.canRedo(),
removeSelected: canvasFocused && !!selectionLength,
replaceElement: canvasFocused && selectionLength == 1,
save: true,
selectAll: true,
selectAll: canvasFocused,
setColor: !!selectionLength,
spaceTool: !inputActive,
undo: commandStack.canUndo(),
spaceTool: canvasFocused,
undo: canvasFocused && commandStack.canUndo(),
zoom: true
};

// ensure backwards compatibility
// https://github.com/camunda/camunda-modeler/commit/78357e3ed9e6e0255ac8225fbdf451a90457e8bf#diff-bd5be70c4e5eadf1a316c16085a72f0fL17
const inputActive = isInputActive();
newState.bpmn = true;
newState.editable = true;
newState.elementsSelected = !!selectionLength;
Expand Down Expand Up @@ -871,6 +865,9 @@ export class BpmnEditor extends CachedComponent {
},
propertiesPanel: {
layout: layout.propertiesPanel
},
keyboard: {
bind: false
}
});

Expand Down
21 changes: 1 addition & 20 deletions client/src/app/tabs/bpmn/__tests__/BpmnEditorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,25 +372,6 @@ describe('<BpmnEditor>', function() {
it('propertiesPanel.focusout', expectHandleChanged('propertiesPanel.focusout'));


it('directEditing.activate', expectHandleChanged('directEditing.activate'));


it('directEditing.deactivate', expectHandleChanged('directEditing.deactivate'));


it('searchPad.opened', expectHandleChanged('searchPad.opened'));


it('searchPad.closed', expectHandleChanged('searchPad.closed'));


it('popupMenu.opened', expectHandleChanged('popupMenu.opened'));


it('popupMenu.closed', expectHandleChanged('popupMenu.closed'));


it('elementTemplates.select', expectHandleChanged('elementTemplates.select'));
});


Expand Down Expand Up @@ -626,6 +607,7 @@ describe('<BpmnEditor>', function() {
// then
expect(state).to.include({
align: false,
canvasFocused: true,
copy: false,
defaultCopyCutPaste: false,
defaultUndoRedo: false,
Expand All @@ -635,7 +617,6 @@ describe('<BpmnEditor>', function() {
find: true,
globalConnectTool: true,
handTool: true,
inputActive: false,
lassoTool: true,
moveCanvas: true,
moveToOrigin: true,
Expand Down
58 changes: 26 additions & 32 deletions client/src/app/tabs/cloud-bpmn/BpmnEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,7 @@ export class BpmnEditor extends CachedComponent {
'elements.copied',
'propertiesPanel.focusin',
'propertiesPanel.focusout',
'directEditing.activate',
'directEditing.deactivate',
'searchPad.closed',
'searchPad.opened',
'popupMenu.opened',
'popupMenu.closed',
'feelPopup.opened',
'feelPopup.closed',
'feelPopup.focusin',
'feelPopup.focusout',
'elementTemplates.select'
'canvas.focus.changed',
].forEach((event) => {
modeler[fn](event, this.handleChanged);
});
Expand Down Expand Up @@ -398,45 +388,46 @@ export class BpmnEditor extends CachedComponent {

const selectionLength = selection.get().length;

const inputActive = isInputActive();
const canvasFocused = modeler.get('canvas').isFocused();

const newState = {
align: selectionLength > 1,
appendElement: !inputActive,
appendElement: canvasFocused,
canvasFocused,
close: true,
copy: !!selectionLength,
cut: false,
createElement: !inputActive,
defaultCopyCutPaste: inputActive,
defaultUndoRedo: inputActive,
createElement: canvasFocused,
defaultCopyCutPaste: !canvasFocused,
defaultUndoRedo: !canvasFocused,
dirty,
distribute: selectionLength > 2,
editLabel: !inputActive && !!selectionLength,
editLabel: canvasFocused && selectionLength === 1,
exportAs: EXPORT_AS,
find: !inputActive,
globalConnectTool: !inputActive,
handTool: !inputActive,
inputActive,
lassoTool: !inputActive,
moveCanvas: !inputActive,
moveToOrigin: !inputActive,
moveSelection: !inputActive && !!selectionLength,
find: canvasFocused,
globalConnectTool: canvasFocused,
handTool: canvasFocused,
lassoTool: canvasFocused,
moveCanvas: canvasFocused,
moveToOrigin: canvasFocused,
moveSelection: canvasFocused && !!selectionLength,
paste: !modeler.get('clipboard').isEmpty(),
platform: 'cloud',
propertiesPanel: true,
redo: commandStack.canRedo(),
removeSelected: !!selectionLength || inputActive,
replaceElement: !!selectionLength && selectionLength == 1 && !inputActive,
redo: canvasFocused && commandStack.canRedo(),
removeSelected: canvasFocused && !!selectionLength,
replaceElement: canvasFocused && selectionLength == 1,
save: true,
selectAll: true,
selectAll: canvasFocused,
setColor: !!selectionLength,
spaceTool: !inputActive,
undo: commandStack.canUndo(),
spaceTool: canvasFocused,
undo: canvasFocused && commandStack.canUndo(),
zoom: true
};

// ensure backwards compatibility
// https://github.com/camunda/camunda-modeler/commit/78357e3ed9e6e0255ac8225fbdf451a90457e8bf#diff-bd5be70c4e5eadf1a316c16085a72f0fL17
const inputActive = isInputActive();
newState.bpmn = true;
newState.editable = true;
newState.elementsSelected = !!selectionLength;
Expand Down Expand Up @@ -845,7 +836,10 @@ export class BpmnEditor extends CachedComponent {
feelPopupContainer: '.bjs-container',
layout: layout.propertiesPanel
},
elementTemplateChooser: false
elementTemplateChooser: false,
keyboard: {
bind: false
}
});

const commandStack = modeler.get('commandStack');
Expand Down
21 changes: 1 addition & 20 deletions client/src/app/tabs/cloud-bpmn/__tests__/BpmnEditorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,25 +371,6 @@ describe('cloud-bpmn - <BpmnEditor>', function() {
it('propertiesPanel.focusout', expectHandleChanged('propertiesPanel.focusout'));


it('directEditing.activate', expectHandleChanged('directEditing.activate'));


it('directEditing.deactivate', expectHandleChanged('directEditing.deactivate'));


it('searchPad.opened', expectHandleChanged('searchPad.opened'));


it('searchPad.closed', expectHandleChanged('searchPad.closed'));


it('popupMenu.opened', expectHandleChanged('popupMenu.opened'));


it('popupMenu.closed', expectHandleChanged('popupMenu.closed'));


it('elementTemplates.select', expectHandleChanged('elementTemplates.select'));
});


Expand Down Expand Up @@ -625,6 +606,7 @@ describe('cloud-bpmn - <BpmnEditor>', function() {
// then
expect(state).to.include({
align: false,
canvasFocused: true,
copy: false,
defaultCopyCutPaste: false,
defaultUndoRedo: false,
Expand All @@ -634,7 +616,6 @@ describe('cloud-bpmn - <BpmnEditor>', function() {
find: true,
globalConnectTool: true,
handTool: true,
inputActive: false,
lassoTool: true,
moveCanvas: true,
moveToOrigin: true,
Expand Down
27 changes: 17 additions & 10 deletions client/src/app/tabs/cloud-dmn/DmnEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,18 +401,22 @@ export class DmnEditor extends CachedComponent {
let editMenu;

if (activeView.type === 'drd') {

const canvasFocused = activeViewer.get('canvas').isFocused();

assign(newState, {
align: selectionLength > 1,
defaultCopyCutPaste: inputActive,
defaultUndoRedo: inputActive,
canvasFocused,
defaultCopyCutPaste: !canvasFocused,
defaultUndoRedo: !canvasFocused,
distribute: selectionLength > 2,
editLabel: !inputActive && !!selectionLength,
find: !inputActive,
lassoTool: !inputActive,
moveCanvas: !inputActive,
moveSelection: !inputActive && !!selectionLength,
removeSelected: inputActive || !!selectionLength,
selectAll: true,
editLabel: canvasFocused && !!selectionLength,
find: canvasFocused,
lassoTool: canvasFocused,
moveCanvas: canvasFocused,
moveSelection: canvasFocused && !!selectionLength,
removeSelected: !canvasFocused || !!selectionLength,
selectAll: canvasFocused,
zoom: true
});

Expand Down Expand Up @@ -1000,7 +1004,10 @@ export class DmnEditor extends CachedComponent {

const modeler = new CamundaDmnModeler({
...options,
position: 'absolute'
position: 'absolute',
keyboard: {
bind: false
}
});

const stackIdx = modeler.getStackIdx();
Expand Down
11 changes: 0 additions & 11 deletions client/src/app/tabs/cmmn/__tests__/CmmnEditorSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,6 @@ describe('<CmmnEditor>', function() {
it('propertiesPanel.focusout', expectHandleChanged('propertiesPanel.focusout'));


it('directEditing.activate', expectHandleChanged('directEditing.activate'));


it('directEditing.deactivate', expectHandleChanged('directEditing.deactivate'));


it('searchPad.opened', expectHandleChanged('searchPad.opened'));


it('searchPad.closed', expectHandleChanged('searchPad.closed'));

});


Expand Down
27 changes: 17 additions & 10 deletions client/src/app/tabs/dmn/DmnEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,18 +401,22 @@ export class DmnEditor extends CachedComponent {
let editMenu;

if (activeView.type === 'drd') {

const canvasFocused = activeViewer.get('canvas').isFocused();

assign(newState, {
align: selectionLength > 1,
defaultCopyCutPaste: inputActive,
defaultUndoRedo: inputActive,
canvasFocused,
defaultCopyCutPaste: !canvasFocused,
defaultUndoRedo: !canvasFocused,
distribute: selectionLength > 2,
editLabel: !inputActive && !!selectionLength,
find: !inputActive,
lassoTool: !inputActive,
moveCanvas: !inputActive,
moveSelection: !inputActive && !!selectionLength,
removeSelected: inputActive || !!selectionLength,
selectAll: true,
editLabel: canvasFocused && !!selectionLength,
find: canvasFocused,
lassoTool: canvasFocused,
moveCanvas: canvasFocused,
moveSelection: canvasFocused && !!selectionLength,
removeSelected: !canvasFocused || !!selectionLength,
selectAll: canvasFocused,
zoom: true
});

Expand Down Expand Up @@ -1000,7 +1004,10 @@ export class DmnEditor extends CachedComponent {

const modeler = new CamundaDmnModeler({
...options,
position: 'absolute'
position: 'absolute',
keyboard: {
bind: false
}
});

const stackIdx = modeler.getStackIdx();
Expand Down
4 changes: 4 additions & 0 deletions client/src/styles/_base.less
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ body {
outline-color: var(--focus-outline-color);
}

.djs-container svg:focus {
outline: none;
}

.bjs-powered-by {
display: none;
}
Expand Down
Loading

0 comments on commit fa33f00

Please sign in to comment.