import { LitElementWw } from '@webwriter/lit'; import { html, css, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { v4 as uuidv4 } from 'uuid'; import { GraphNode } from './src/definitions/GraphNode'; import { Arrow } from './src/definitions/Arrow'; import { ItemList } from './src/definitions/ItemList'; import { drawButton } from './src/modules/drawer/drawButton'; import { drawGraphNode, drawNodeAnchors } from './src/modules/drawer/drawGraphNode'; import { drawArrow, drawTempArrow, generateArrowPoints, drawArrowAnchor } from './src/modules/drawer/drawArrow'; import { drawSelectionField } from './src/modules/drawer/drawSelectionField'; import { handleNodeDragStart, handleArrowDragStart, handleMultipleNodesDragStart, } from './src/modules/handler/mouseDownHandler'; import { handleGrabRelease, handleNodeDragStop, handleArrowCreation } from './src/modules/handler/mouseUpHandler'; import { handleSequenceSelection } from './src/modules/handler/handleSequenceSelection'; import { handleGraphNodeDoubleClick, handleArrowDoubleClick } from './src/modules/handler/doubleClickHandler'; import { toggleMenu } from './src/modules/ui/toggleMenu'; import { addHelp, renderHelpList } from './src/modules/ui/helpMenu'; import { addTask, renderTasks } from './src/modules/ui/taskMenu'; import { createTooltip, removeTooltip, updateDisabledState, grabCanvas, autoDeleteEmptyItems, } from './src/modules/ui/generalUI'; import { snapNodePosition, removeOldConnection, isNodeInRectangle, findLastGraphNode, findGraphNodeLastIndex, } from './src/modules/helper/utilities'; import { isArrowClicked } from './src/modules/helper/arrowHelper'; import { getAnchors, highlightAnchor } from './src/modules/helper/anchorHelper'; import { createArrowsFromGraphNodes, updatePresetIds } from './src/modules/helper/presetHelper'; import { papWidgetStyles } from './src/modules/styles/styles'; import { CustomPrompt } from './src/components/custom-prompt'; import './src/components/custom-prompt'; import { ConfirmPrompt } from './src/components/confirm-prompt'; import './src/components/confirm-prompt'; import { PropertyValueMap } from '@lit/reactive-element'; @customElement('webwriter-flowchart') export class FlowchartWidget extends LitElementWw { @property({ type: Array, reflect: true, attribute: true }) accessor graphNodes: GraphNode[] = []; @property({ type: Object }) accessor selectedNode: GraphNode; @property({ type: Array }) accessor arrows: Arrow[] = []; @property({ type: Object }) accessor selectedArrow: Arrow; getGraphNodes = () => this.graphNodes; getArrows = () => this.arrows; @property({ type: Array, reflect: true, attribute: true }) accessor taskList: ItemList[] = []; @property({ type: Array, reflect: true, attribute: true }) accessor helpList: ItemList[] = []; @property({ type: Number, reflect: true, attribute: true }) accessor height: number = 400; @property({ type: Number }) accessor currentHeight: number = this.height; @property({ type: Object }) accessor graphSettings = { font: 'Courier New', fontSize: 16, theme: 'standard' }; @property({ type: Number, reflect: true, attribute: true }) accessor zoomLevel: number = 100; // in Prozent private gridSize: number = 50; private dotSize: number = 1.5; @property({ type: Number, reflect: true, attribute: true }) accessor canvasOffsetX: number = 0; @property({ type: Number, reflect: true, attribute: true }) accessor canvasOffsetY: number = 0; @property({ type: Boolean, reflect: true, attribute: true }) accessor allowStudentEdit: boolean = false; @property({ type: Boolean, reflect: true, attribute: true }) accessor allowStudentPan: boolean = false; @property({ type: String, reflect: true, attribute: true }) accessor font = 'Courier New'; @property({ type: Number, reflect: true, attribute: true }) accessor fontSize = 16; @property({ type: String, reflect: true, attribute: true }) accessor theme = 'standard'; @property({ type: Boolean }) accessor fullscreen = false; static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }; private canvas: HTMLCanvasElement; private ctx: CanvasRenderingContext2D; private isDragging = false; private draggedNode: GraphNode; private dragOffset = { x: 0, y: 0 }; private draggedNodes: GraphNode[] = []; private isDrawingArrow = false; private arrowStart?: { node: GraphNode; anchor: number }; private tempArrowEnd?: { x: number; y: number }; private isGrabbing = false; private grabStartPosition?: { x: number; y: number }; private grabStartOffset?: { x: number; y: number }; private hoveredAnchor?: { element: GraphNode; anchor: number }; private isArrowAnchorHovered: boolean; private _isSelectingSequence = false; private selectedSequence: { id: string; order: number; type: string }[] = []; getSelectedSequence = () => this.selectedSequence; private activeSequenceButton: HTMLButtonElement | null = null; getActiveSequenceButton = () => this.activeSequenceButton; setActiveSequenceButton = (btn: HTMLButtonElement | null) => { this.activeSequenceButton = btn; }; get isSelectingSequence() { return this._isSelectingSequence; } set isSelectingSequence(value: boolean) { const oldValue = this._isSelectingSequence; this._isSelectingSequence = value; if (oldValue !== value) { //this.showSolutionMenu(); } } private promptType: 'node' | 'arrow' | null; private promptIndex: number | null; @property({ type: String }) accessor solutionMessage: string = ''; @property({ type: Boolean }) accessor showSolution: boolean = false; @property({ type: Array }) accessor selectedNodes: GraphNode[] = []; private selectionRectangle?: { x: number; y: number; width: number; height: number }; private checkOffset = true; static style = papWidgetStyles; static scopedElements = { 'custom-prompt': CustomPrompt, 'confirm-prompt': ConfirmPrompt }; public isEditable(): boolean { return this.contentEditable === 'true' || this.contentEditable === ''; } render() { // console.log('render', this); return html` ${this.isEditable() ? this.renderToolMenu() : ''}
${this.solutionMessage}