js-draw
Version:
Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.
100 lines (99 loc) • 4.22 kB
JavaScript
import { EraserMode } from '../../tools/Eraser.mjs';
import { EditorEventType } from '../../types.mjs';
import { toolbarCSSPrefix } from '../constants.mjs';
import BaseToolWidget from './BaseToolWidget.mjs';
import makeThicknessSlider from './components/makeThicknessSlider.mjs';
class EraserToolWidget extends BaseToolWidget {
constructor(editor, tool, localizationTable) {
super(editor, tool, 'eraser-tool-widget', localizationTable);
this.tool = tool;
this.updateInputs = () => { };
this.editor.notifier.on(EditorEventType.ToolUpdated, (toolEvt) => {
if (toolEvt.kind === EditorEventType.ToolUpdated && toolEvt.tool === this.tool) {
this.updateInputs();
this.updateIcon();
}
});
}
getHelpText() {
return this.localizationTable.eraserDropdown__baseHelpText;
}
getTitle() {
return this.localizationTable.eraser;
}
makeIconForType(mode) {
return this.editor.icons.makeEraserIcon(this.tool.getThickness(), mode);
}
createIcon() {
return this.makeIconForType(this.tool.getModeValue().get());
}
makeEraserTypeSelector(helpDisplay) {
const container = document.createElement('div');
const labelElement = document.createElement('label');
const checkboxElement = document.createElement('input');
checkboxElement.id = `${toolbarCSSPrefix}eraserToolWidget-${EraserToolWidget.idCounter++}`;
labelElement.htmlFor = checkboxElement.id;
labelElement.innerText = this.localizationTable.fullStrokeEraser;
checkboxElement.type = 'checkbox';
checkboxElement.oninput = () => {
this.tool
.getModeValue()
.set(checkboxElement.checked ? EraserMode.FullStroke : EraserMode.PartialStroke);
};
const updateValue = () => {
checkboxElement.checked = this.tool.getModeValue().get() === EraserMode.FullStroke;
};
container.replaceChildren(labelElement, checkboxElement);
helpDisplay?.registerTextHelpForElement(container, this.localizationTable.eraserDropdown__fullStrokeEraserHelpText);
return {
addTo: (parent) => {
parent.appendChild(container);
},
updateValue,
};
}
fillDropdown(dropdown, helpDisplay) {
const container = document.createElement('div');
container.classList.add(`${toolbarCSSPrefix}spacedList`, `${toolbarCSSPrefix}nonbutton-controls-main-list`);
const thicknessSlider = makeThicknessSlider(this.editor, (thickness) => {
this.tool.setThickness(thickness);
});
thicknessSlider.setBounds(10, 55);
helpDisplay?.registerTextHelpForElement(thicknessSlider.container, this.localizationTable.eraserDropdown__thicknessHelpText);
const modeSelector = this.makeEraserTypeSelector(helpDisplay);
this.updateInputs = () => {
thicknessSlider.setValue(this.tool.getThickness());
modeSelector.updateValue();
};
this.updateInputs();
container.replaceChildren(thicknessSlider.container);
modeSelector.addTo(container);
dropdown.replaceChildren(container);
return true;
}
serializeState() {
return {
...super.serializeState(),
thickness: this.tool.getThickness(),
mode: this.tool.getModeValue().get(),
};
}
deserializeFrom(state) {
super.deserializeFrom(state);
if (state.thickness) {
const parsedThickness = parseFloat(state.thickness);
if (typeof parsedThickness !== 'number' || !isFinite(parsedThickness)) {
throw new Error(`Deserializing property ${parsedThickness} is not a number or is not finite.`);
}
this.tool.setThickness(parsedThickness);
}
if (state.mode) {
const mode = state.mode;
if (Object.values(EraserMode).includes(mode)) {
this.tool.getModeValue().set(mode);
}
}
}
}
EraserToolWidget.idCounter = 0;
export default EraserToolWidget;