Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.1.3 #6

Merged
merged 3 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ const workspace = Blockly.inject('blocklyDiv', options);
// Initialize plugin.
const multiselectPlugin = new Multiselect(workspace);
multiselectPlugin.init(options);

// Focus on the workspace.
// The shift drag will only work on the workspace that gets focused.
workspace.getInjectionDiv().focus();
```

## User behavior
Expand All @@ -77,6 +81,9 @@ multiselectPlugin.init(options);
21. When you edit the fields while selecting multiple blocks, we will automatically apply that to all the blocks with the same type.
22. (MIT App Inventor-only feature) Double click to collapse/expand currently selected blocks, enable with Blockly option `useDoubleClick: true`.

## Known issues
- [ ] Currently, we rely on DragSelect to know which block gets selected. DragSelect seems to listen to the "blocks". However, it actually works by listening to the SVG path element, which is always a rectangle with some transparent parts forming a block. For irregularly shaped blocks, the two blocks' SVG path elements can overlap with each other, so if you shift-click on that area, DragSelect will make both blocks selected. (A fix should be that Blockly implements some kind of API, so that we can know for sure where the block actually locates.)

## API

- `Multiselect.init`: Initialize the plugin.
Expand All @@ -86,7 +93,7 @@ multiselectPlugin.init(options);
- `inMultipleSelectionModeWeakMap`: The WeakMap storing whether the plugin is in multiple selection mode by workspace svg.

## Credit
- [ds.min.js](lib/ds.min.js): This plugin uses [a patched version of DragSelect](https://github.com/ThibaultJanBeyer/DragSelect/pull/128) to realize "drag a rectangle to select multiple blocks" feature.
- [DragSelect](https://github.com/ThibaultJanBeyer/DragSelect): This plugin uses DragSelect to realize the "drag a rectangle to select multiple blocks" feature (A [PR](https://github.com/ThibaultJanBeyer/DragSelect/pull/143) made all this possible, and it has got merged into [v2.4.4](https://github.com/ThibaultJanBeyer/DragSelect/releases/tag/v2.4.4)).
- [select.svg](test/media/select.svg) & [unselect.svg](test/media/unselect.svg): Free icons downloaded at [Icons8](https://icons8.com).
- This plugin is part of the achievement by Songlin Jiang([@HollowMan6](https://github.com/HollowMan6)) participating the [Google Summer of Code 2022](https://summerofcode.withgoogle.com/programs/2022/projects/9wF06HWE) at [MIT App Inventor](https://github.com/mit-cml).

Expand Down
4,562 changes: 2,310 additions & 2,252 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mit-app-inventor/blockly-plugin-workspace-multiselect",
"version": "0.1.2",
"version": "0.1.3",
"description": "A Blockly plugin that allows to drag, select and doing actions on multiple blocks in the workspace.",
"scripts": {
"audit:fix": "blockly-scripts auditFix",
Expand Down Expand Up @@ -38,13 +38,16 @@
"dist",
"src"
],
"dependencies": {
"dragselect": "^2.5.4"
},
"devDependencies": {
"@blockly/dev-scripts": "^1.2.26",
"@blockly/dev-tools": "^4.0.2",
"blockly": "^8.0.4"
"@blockly/dev-scripts": "^1.2.28",
"@blockly/dev-tools": "^5.0.2",
"blockly": "^9.1.0"
},
"peerDependencies": {
"blockly": "^8.0.4"
"blockly": "^9.1.0"
HollowMan6 marked this conversation as resolved.
Show resolved Hide resolved
},
"publishConfig": {},
"eslintConfig": {
Expand Down
2 changes: 0 additions & 2 deletions src/lib/ds.min.js

This file was deleted.

12 changes: 6 additions & 6 deletions src/multiselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ export class Multiselect {
return !block.isInFlyout && block.isMovable() &&
block.workspace.options.collapse;
};
if (Blockly.selected && preCondition(Blockly.selected)) {
if (Blockly.getSelected() && preCondition(Blockly.getSelected())) {
if (ws.doubleClickPid_) {
clearTimeout(ws.doubleClickPid_);
ws.doubleClickPid_ = undefined;
if (Blockly.selected.id === ws.doubleClickBlock_) {
const state = !Blockly.selected.isCollapsed();
if (Blockly.getSelected().id === ws.doubleClickBlock_) {
const state = !Blockly.getSelected().isCollapsed();
const maybeCollapse = function(block) {
if (block && preCondition(block) &&
!hasSelectedParent(block)) {
Expand All @@ -155,8 +155,8 @@ export class Multiselect {
};
Blockly.Events.setGroup(true);
const blockSelection = blockSelectionWeakMap.get(ws);
if (Blockly.selected && !blockSelection.size) {
maybeCollapse(Blockly.selected);
if (Blockly.getSelected() && !blockSelection.size) {
maybeCollapse(Blockly.getSelected());
}
blockSelection.forEach(function(id) {
const block = ws.getBlockById(id);
Expand All @@ -169,7 +169,7 @@ export class Multiselect {
}
}
if (!ws.doubleClickPid_) {
ws.doubleClickBlock_ = Blockly.selected.id;
ws.doubleClickBlock_ = Blockly.getSelected().id;
ws.doubleClickPid_ = setTimeout(function() {
ws.doubleClickPid_ = undefined;
}, 500);
Expand Down
5 changes: 3 additions & 2 deletions src/multiselect_contextmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,9 @@ const registerSelectAll = function() {
},
callback: function(scope) {
const blockSelection = blockSelectionWeakMap.get(scope.workspace);
if (Blockly.selected && !blockSelection.has(Blockly.selected.id)) {
Blockly.selected.pathObject.updateSelected(false);
if (Blockly.getSelected() &&
!blockSelection.has(Blockly.getSelected().id)) {
Blockly.getSelected().pathObject.updateSelected(false);
Blockly.common.setSelected(null);
}

Expand Down
17 changes: 9 additions & 8 deletions src/multiselect_controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import * as Blockly from 'blockly/core';

import DragSelect from './lib/ds.min';
import DragSelect from 'dragselect';
import {blockSelectionWeakMap, inMultipleSelectionModeWeakMap} from './global';

/**
Expand Down Expand Up @@ -296,8 +296,9 @@ export class MultiselectControls {
*/
updateMultiselect() {
if (!inMultipleSelectionModeWeakMap.get(this.workspace_)) {
if (!Blockly.selected ||
(Blockly.selected && !this.blockSelection.has(Blockly.selected.id))) {
if (!Blockly.getSelected() ||
(Blockly.getSelected() &&
!this.blockSelection.has(Blockly.getSelected().id))) {
// When not in multiple selection mode and Blockly selects a block not
// in currently selected set or unselects, clear the selected set.
this.blockSelection.forEach((id) => {
Expand All @@ -307,10 +308,10 @@ export class MultiselectControls {
}
});
this.blockSelection.clear();
this.updateBlocks_(Blockly.selected);
this.updateBlocks_(Blockly.getSelected());
}
} else if (this.justUnselectedBlock_ && Blockly.selected &&
Blockly.selected.id === this.justUnselectedBlock_.id) {
} else if (this.justUnselectedBlock_ && Blockly.getSelected() &&
Blockly.getSelected().id === this.justUnselectedBlock_.id) {
// Update the Blockly selected block when that block is
// no longer selected in our set.
if (this.blockSelection.size) {
Expand Down Expand Up @@ -393,9 +394,9 @@ export class MultiselectControls {
}
// Ensure that at least Blockly select one of the blocks in the
// selection set, or clear the Blockly selection if our set is empty.
if (!this.blockSelection.size && Blockly.selected) {
if (!this.blockSelection.size && Blockly.getSelected()) {
Blockly.common.setSelected(null);
} else if (this.blockSelection.size && !Blockly.selected) {
} else if (this.blockSelection.size && !Blockly.getSelected()) {
Blockly.common.setSelected(
this.workspace_.getBlockById(
this.blockSelection.keys().next().value));
Expand Down
4 changes: 2 additions & 2 deletions src/multiselect_patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ import * as Blockly from 'blockly/core';
* Disable the drag surface.
* @override
*/
Blockly.utils.svgMath.is3dSupported = function() {
return false;
Blockly.WorkspaceSvg.prototype.getBlockDragSurface = function() {
return null;
};
5 changes: 3 additions & 2 deletions src/multiselect_shortcut.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,9 @@ const registeSelectAll = function() {
// Prevent the default text all selection behavior.
e.preventDefault();
const blockSelection = blockSelectionWeakMap.get(workspace);
if (Blockly.selected && !blockSelection.has(Blockly.selected.id)) {
Blockly.selected.pathObject.updateSelected(false);
if (Blockly.getSelected() &&
!blockSelection.has(Blockly.getSelected().id)) {
Blockly.getSelected().pathObject.updateSelected(false);
Blockly.common.setSelected(null);
}
workspace.getTopBlocks().forEach(function(block) {
Expand Down
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function createWorkspace(blocklyDiv, options) {
const multiselectPlugin = new Multiselect(workspace);
multiselectPlugin.init(options);

workspace.getInjectionDiv().focus();
return workspace;
}

Expand Down