mirror of
https://github.com/google/blockly.git
synced 2026-01-08 17:40:09 +01:00
feat!: Add context menu options for workspace comments (#8035)
* feat: add context menu support and migrate easy options * feat: pass events to context menu options * chore: migrate final comment context menu option * feat: add exports for comment context menu items * chore: PR comments
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
import type {Block} from './block.js';
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as clipboard from './clipboard.js';
|
||||
import {config} from './config.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import type {
|
||||
@@ -19,15 +18,11 @@ import type {
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {Menu} from './menu.js';
|
||||
import {MenuItem} from './menuitem.js';
|
||||
import {Msg} from './msg.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import {Rect} from './utils/rect.js';
|
||||
import * as serializationBlocks from './serialization/blocks.js';
|
||||
import * as svgMath from './utils/svg_math.js';
|
||||
import * as WidgetDiv from './widgetdiv.js';
|
||||
import {WorkspaceCommentSvg} from './workspace_comment_svg.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as Xml from './xml.js';
|
||||
import * as common from './common.js';
|
||||
|
||||
@@ -69,7 +64,7 @@ let menu_: Menu | null = null;
|
||||
* @param rtl True if RTL, false if LTR.
|
||||
*/
|
||||
export function show(
|
||||
e: Event,
|
||||
e: PointerEvent,
|
||||
options: (ContextMenuOption | LegacyContextMenuOption)[],
|
||||
rtl: boolean,
|
||||
) {
|
||||
@@ -78,7 +73,7 @@ export function show(
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
const menu = populate_(options, rtl);
|
||||
const menu = populate_(options, rtl, e);
|
||||
menu_ = menu;
|
||||
|
||||
position_(menu, e, rtl);
|
||||
@@ -95,11 +90,13 @@ export function show(
|
||||
*
|
||||
* @param options Array of menu options.
|
||||
* @param rtl True if RTL, false if LTR.
|
||||
* @param e The event that triggered the context menu to open.
|
||||
* @returns The menu that will be shown on right click.
|
||||
*/
|
||||
function populate_(
|
||||
options: (ContextMenuOption | LegacyContextMenuOption)[],
|
||||
rtl: boolean,
|
||||
e: PointerEvent,
|
||||
): Menu {
|
||||
/* Here's what one option object looks like:
|
||||
{text: 'Make It So',
|
||||
@@ -124,7 +121,7 @@ function populate_(
|
||||
// will not be expecting a scope parameter, so there should be
|
||||
// no problems. Just assume it is a ContextMenuOption and we'll
|
||||
// pass undefined if it's not.
|
||||
option.callback((option as ContextMenuOption).scope);
|
||||
option.callback((option as ContextMenuOption).scope, e);
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
@@ -266,125 +263,3 @@ export function callbackFactory(
|
||||
return newBlock;
|
||||
};
|
||||
}
|
||||
|
||||
// Helper functions for creating context menu options.
|
||||
|
||||
/**
|
||||
* Make a context menu option for deleting the current workspace comment.
|
||||
*
|
||||
* @param comment The workspace comment where the
|
||||
* right-click originated.
|
||||
* @returns A menu option,
|
||||
* containing text, enabled, and a callback.
|
||||
* @internal
|
||||
*/
|
||||
export function commentDeleteOption(
|
||||
comment: WorkspaceCommentSvg,
|
||||
): LegacyContextMenuOption {
|
||||
const deleteOption = {
|
||||
text: Msg['REMOVE_COMMENT'],
|
||||
enabled: true,
|
||||
callback: function () {
|
||||
eventUtils.setGroup(true);
|
||||
comment.dispose();
|
||||
eventUtils.setGroup(false);
|
||||
},
|
||||
};
|
||||
return deleteOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a context menu option for duplicating the current workspace comment.
|
||||
*
|
||||
* @param comment The workspace comment where the
|
||||
* right-click originated.
|
||||
* @returns A menu option,
|
||||
* containing text, enabled, and a callback.
|
||||
* @internal
|
||||
*/
|
||||
export function commentDuplicateOption(
|
||||
comment: WorkspaceCommentSvg,
|
||||
): LegacyContextMenuOption {
|
||||
const duplicateOption = {
|
||||
text: Msg['DUPLICATE_COMMENT'],
|
||||
enabled: true,
|
||||
callback: function () {
|
||||
const data = comment.toCopyData();
|
||||
if (!data) return;
|
||||
clipboard.paste(data, comment.workspace);
|
||||
},
|
||||
};
|
||||
return duplicateOption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a context menu option for adding a comment on the workspace.
|
||||
*
|
||||
* @param ws The workspace where the right-click
|
||||
* originated.
|
||||
* @param e The right-click mouse event.
|
||||
* @returns A menu option, containing text, enabled, and a callback.
|
||||
* comments are not bundled in.
|
||||
* @internal
|
||||
*/
|
||||
export function workspaceCommentOption(
|
||||
ws: WorkspaceSvg,
|
||||
e: Event,
|
||||
): ContextMenuOption {
|
||||
/**
|
||||
* Helper function to create and position a comment correctly based on the
|
||||
* location of the mouse event.
|
||||
*/
|
||||
function addWsComment() {
|
||||
const comment = new WorkspaceCommentSvg(
|
||||
ws,
|
||||
Msg['WORKSPACE_COMMENT_DEFAULT_TEXT'],
|
||||
WorkspaceCommentSvg.DEFAULT_SIZE,
|
||||
WorkspaceCommentSvg.DEFAULT_SIZE,
|
||||
);
|
||||
|
||||
const injectionDiv = ws.getInjectionDiv();
|
||||
// Bounding rect coordinates are in client coordinates, meaning that they
|
||||
// are in pixels relative to the upper left corner of the visible browser
|
||||
// window. These coordinates change when you scroll the browser window.
|
||||
const boundingRect = injectionDiv.getBoundingClientRect();
|
||||
|
||||
// The client coordinates offset by the injection div's upper left corner.
|
||||
const mouseEvent = e as MouseEvent;
|
||||
const clientOffsetPixels = new Coordinate(
|
||||
mouseEvent.clientX - boundingRect.left,
|
||||
mouseEvent.clientY - boundingRect.top,
|
||||
);
|
||||
|
||||
// The offset in pixels between the main workspace's origin and the upper
|
||||
// left corner of the injection div.
|
||||
const mainOffsetPixels = ws.getOriginOffsetInPixels();
|
||||
|
||||
// The position of the new comment in pixels relative to the origin of the
|
||||
// main workspace.
|
||||
const finalOffset = Coordinate.difference(
|
||||
clientOffsetPixels,
|
||||
mainOffsetPixels,
|
||||
);
|
||||
// The position of the new comment in main workspace coordinates.
|
||||
finalOffset.scale(1 / ws.scale);
|
||||
|
||||
const commentX = finalOffset.x;
|
||||
const commentY = finalOffset.y;
|
||||
comment.moveBy(commentX, commentY);
|
||||
if (ws.rendered) {
|
||||
comment.initSvg();
|
||||
comment.render();
|
||||
common.setSelected(comment);
|
||||
}
|
||||
}
|
||||
|
||||
const wsCommentOption = {
|
||||
enabled: true,
|
||||
} as ContextMenuOption;
|
||||
wsCommentOption.text = Msg['ADD_COMMENT'];
|
||||
wsCommentOption.callback = function () {
|
||||
addWsComment();
|
||||
};
|
||||
return wsCommentOption;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user