js-draw
Version:
Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.
241 lines (240 loc) • 10.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const math_1 = require("@js-draw/math");
const RestylableComponent_1 = require("../../components/RestylableComponent");
const uniteCommands_1 = __importDefault(require("../../commands/uniteCommands"));
const SelectionTool_1 = require("../../tools/SelectionTool/SelectionTool");
const types_1 = require("../../types");
const makeColorInput_1 = __importDefault(require("./components/makeColorInput"));
const BaseToolWidget_1 = __importDefault(require("./BaseToolWidget"));
const keybindings_1 = require("./keybindings");
const makeSeparator_1 = __importDefault(require("./components/makeSeparator"));
const constants_1 = require("../constants");
const BaseWidget_1 = __importDefault(require("./BaseWidget"));
const makeButtonGrid_1 = __importDefault(require("./components/makeButtonGrid"));
const ReactiveValue_1 = require("../../util/ReactiveValue");
const makeFormatMenu = (editor, selectionTool, localizationTable) => {
const container = document.createElement('div');
container.classList.add('selection-format-menu', `${constants_1.toolbarCSSPrefix}spacedList`, `${constants_1.toolbarCSSPrefix}indentedList`);
const colorRow = document.createElement('div');
const colorLabel = document.createElement('label');
const colorInputControl = (0, makeColorInput_1.default)(editor, (color) => {
const selection = selectionTool.getSelection();
if (selection) {
const updateStyleCommands = [];
for (const elem of selection.getSelectedObjects()) {
if ((0, RestylableComponent_1.isRestylableComponent)(elem)) {
updateStyleCommands.push(elem.updateStyle({ color }));
}
}
const unitedCommand = (0, uniteCommands_1.default)(updateStyleCommands);
editor.dispatch(unitedCommand);
}
});
const { input: colorInput, container: colorInputContainer } = colorInputControl;
colorLabel.innerText = localizationTable.colorLabel;
const update = () => {
const selection = selectionTool.getSelection();
if (selection && selection.getSelectedItemCount() > 0) {
colorInput.disabled = false;
container.classList.remove('disabled');
const colors = [];
for (const elem of selection.getSelectedObjects()) {
if ((0, RestylableComponent_1.isRestylableComponent)(elem)) {
const color = elem.getStyle().color;
if (color) {
colors.push(color);
}
}
}
colorInputControl.setValue(math_1.Color4.average(colors));
}
else {
colorInput.disabled = true;
container.classList.add('disabled');
colorInputControl.setValue(math_1.Color4.transparent);
}
};
colorRow.replaceChildren(colorLabel, colorInputContainer);
container.replaceChildren(colorRow);
return {
addTo: (parent) => {
parent.appendChild(container);
},
update,
registerHelpText: (helpDisplay) => {
helpDisplay.registerTextHelpForElement(colorRow, localizationTable.selectionDropdown__changeColorHelpText);
colorInputControl.registerWithHelpTextDisplay(helpDisplay);
},
};
};
class LassoSelectToggle extends BaseWidget_1.default {
constructor(editor, tool, localizationTable) {
super(editor, 'selection-mode-toggle', localizationTable);
this.tool = tool;
editor.notifier.on(types_1.EditorEventType.ToolUpdated, (toolEvt) => {
if (toolEvt.kind === types_1.EditorEventType.ToolUpdated && toolEvt.tool === tool) {
this.setSelected(tool.modeValue.get() === SelectionTool_1.SelectionMode.Lasso);
}
});
this.setSelected(false);
}
shouldAutoDisableInReadOnlyEditor() {
return false;
}
setModeFlag(enabled) {
this.tool.modeValue.set(enabled ? SelectionTool_1.SelectionMode.Lasso : SelectionTool_1.SelectionMode.Rectangle);
}
handleClick() {
this.setModeFlag(!this.isSelected());
}
getTitle() {
return this.localizationTable.selectionTool__lassoSelect;
}
createIcon() {
return this.editor.icons.makeSelectionIcon(SelectionTool_1.SelectionMode.Lasso);
}
fillDropdown(_dropdown) {
return false;
}
getHelpText() {
return this.localizationTable.selectionTool__lassoSelect__help;
}
}
class SelectionToolWidget extends BaseToolWidget_1.default {
constructor(editor, tool, localization) {
super(editor, tool, 'selection-tool-widget', localization);
this.tool = tool;
this.updateFormatMenu = () => { };
this.addSubWidget(new LassoSelectToggle(editor, tool, this.localizationTable));
const hasSelection = () => {
const selection = this.tool.getSelection();
return !!selection && selection.getSelectedItemCount() > 0;
};
this.hasSelectionValue = ReactiveValue_1.MutableReactiveValue.fromInitialValue(hasSelection());
// Enable/disable actions based on whether items are selected
this.editor.notifier.on(types_1.EditorEventType.ToolUpdated, (toolEvt) => {
if (toolEvt.kind !== types_1.EditorEventType.ToolUpdated) {
throw new Error('Invalid event type!');
}
if (toolEvt.tool === this.tool) {
this.hasSelectionValue.set(hasSelection());
this.updateFormatMenu();
}
});
tool.modeValue.onUpdate(() => {
this.updateIcon();
});
}
resizeImageToSelection() {
const selection = this.tool.getSelection();
if (selection) {
this.editor.dispatch(this.editor.setImportExportRect(selection.region));
}
}
onKeyPress(event) {
const shortcuts = this.editor.shortcuts;
// Resize image to selection:
// Other keys are handled directly by the selection tool.
if (shortcuts.matchesShortcut(keybindings_1.resizeImageToSelectionKeyboardShortcut, event)) {
this.resizeImageToSelection();
return true;
}
// If we didn't handle the event, allow the superclass to handle it.
if (super.onKeyPress(event)) {
return true;
}
return false;
}
getTitle() {
return this.localizationTable.select;
}
createIcon() {
return this.editor.icons.makeSelectionIcon(this.tool.modeValue.get());
}
getHelpText() {
return this.localizationTable.selectionDropdown__baseHelpText;
}
createSelectionActions(helpDisplay) {
const icons = this.editor.icons;
const grid = (0, makeButtonGrid_1.default)([
{
icon: () => icons.makeDeleteSelectionIcon(),
label: this.localizationTable.deleteSelection,
onCreated: (button) => {
helpDisplay?.registerTextHelpForElement(button, this.localizationTable.selectionDropdown__deleteHelpText);
},
onClick: () => {
const selection = this.tool.getSelection();
this.editor.dispatch(selection.deleteSelectedObjects());
this.tool.clearSelection();
},
enabled: this.hasSelectionValue,
},
{
icon: () => icons.makeDuplicateSelectionIcon(),
label: this.localizationTable.duplicateSelection,
onCreated: (button) => {
helpDisplay?.registerTextHelpForElement(button, this.localizationTable.selectionDropdown__duplicateHelpText);
},
onClick: async () => {
const selection = this.tool.getSelection();
const command = await selection?.duplicateSelectedObjects();
if (command) {
this.editor.dispatch(command);
}
},
enabled: this.hasSelectionValue,
},
{
icon: () => icons.makeResizeImageToSelectionIcon(),
label: this.localizationTable.resizeImageToSelection,
onCreated: (button) => {
helpDisplay?.registerTextHelpForElement(button, this.localizationTable.selectionDropdown__resizeToHelpText);
},
onClick: () => {
this.resizeImageToSelection();
},
enabled: this.hasSelectionValue,
},
], 3);
return { container: grid.container };
}
fillDropdown(dropdown, helpDisplay) {
super.fillDropdown(dropdown, helpDisplay);
const controlsContainer = document.createElement('div');
controlsContainer.classList.add(`${constants_1.toolbarCSSPrefix}nonbutton-controls-main-list`);
dropdown.appendChild(controlsContainer);
// Actions (duplicate, delete, etc.)
(0, makeSeparator_1.default)().addTo(controlsContainer);
const actions = this.createSelectionActions(helpDisplay);
controlsContainer.appendChild(actions.container);
// Formatting
(0, makeSeparator_1.default)(this.localizationTable.reformatSelection).addTo(controlsContainer);
const formatMenu = makeFormatMenu(this.editor, this.tool, this.localizationTable);
formatMenu.addTo(controlsContainer);
this.updateFormatMenu = () => formatMenu.update();
if (helpDisplay) {
formatMenu.registerHelpText(helpDisplay);
}
formatMenu.update();
return true;
}
serializeState() {
return {
...super.serializeState(),
selectionMode: this.tool.modeValue.get(),
};
}
deserializeFrom(state) {
super.deserializeFrom(state);
const isValidSelectionMode = Object.values(SelectionTool_1.SelectionMode).includes(state.selectionMode);
if (isValidSelectionMode) {
this.tool.modeValue.set(state.selectionMode);
}
}
}
exports.default = SelectionToolWidget;