2024-08-08 16:21:19 +05:30
|
|
|
import React from "react"
|
|
|
|
|
import { NotImplementedError } from "../../utils/errors"
|
|
|
|
|
|
|
|
|
|
import Tools from "../constants/tools"
|
|
|
|
|
import Layouts from "../constants/layouts"
|
|
|
|
|
import Cursor from "../constants/cursor"
|
2024-09-09 19:06:03 +05:30
|
|
|
import { toSnakeCase } from "../utils/utils"
|
|
|
|
|
import EditableDiv from "../../components/editableDiv"
|
2024-09-16 22:04:24 +05:30
|
|
|
import DraggableWrapper from "../../components/draggable/draggable"
|
|
|
|
|
import DroppableWrapper from "../../components/draggable/droppable"
|
|
|
|
|
|
|
|
|
|
import { ActiveWidgetContext } from "../activeWidgetContext"
|
2024-09-17 11:55:21 +05:30
|
|
|
import { DragWidgetProvider } from "./draggableWidgetContext"
|
|
|
|
|
import WidgetDraggable from "./widgetDragDrop"
|
2024-08-08 16:21:19 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base class to be extended
|
|
|
|
|
*/
|
2024-09-15 12:08:29 +05:30
|
|
|
class Widget extends React.Component {
|
2024-08-08 16:21:19 +05:30
|
|
|
|
2024-08-08 22:49:14 +05:30
|
|
|
static widgetType = "widget"
|
2024-08-08 16:21:19 +05:30
|
|
|
|
2024-09-16 22:04:24 +05:30
|
|
|
// static contextType = ActiveWidgetContext
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
constructor(props) {
|
2024-08-08 16:21:19 +05:30
|
|
|
super(props)
|
2024-08-08 22:49:14 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
const { id, widgetName, canvasRef } = props
|
2024-09-12 19:20:46 +05:30
|
|
|
// console.log("Id: ", id)
|
2024-08-08 16:21:19 +05:30
|
|
|
// this id has to be unique inside the canvas, it will be set automatically and should never be changed
|
2024-08-08 22:49:14 +05:30
|
|
|
this.__id = id
|
2024-09-13 22:05:38 +05:30
|
|
|
this.canvas = canvasRef?.current || null // canvasContainerRef, because some events work properly only if attached to the container
|
2024-09-09 19:06:03 +05:30
|
|
|
|
|
|
|
|
// this._selected = false
|
2024-08-08 16:21:19 +05:30
|
|
|
this._disableResize = false
|
|
|
|
|
this._disableSelection = false
|
|
|
|
|
|
2024-09-12 19:20:46 +05:30
|
|
|
this._parent = "" // id of the parent widget, default empty string
|
|
|
|
|
this._children = [] // id's of all the child widgets
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
this.minSize = { width: 50, height: 50 } // disable resizing below this number
|
|
|
|
|
this.maxSize = { width: 500, height: 500 } // disable resizing above this number
|
2024-09-10 21:34:05 +05:30
|
|
|
|
2024-08-08 16:21:19 +05:30
|
|
|
this.cursor = Cursor.POINTER
|
|
|
|
|
|
|
|
|
|
this.icon = "" // antd icon name representing this widget
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
this.elementRef = React.createRef()
|
2024-08-08 16:21:19 +05:30
|
|
|
|
|
|
|
|
this.functions = {
|
2024-09-15 12:08:29 +05:30
|
|
|
"load": { "args1": "number", "args2": "string" }
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.layout = Layouts.PACK
|
|
|
|
|
this.boundingRect = {
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
height: 100,
|
|
|
|
|
width: 100
|
2024-09-15 12:08:29 +05:30
|
|
|
}
|
2024-08-08 16:21:19 +05:30
|
|
|
|
2024-08-08 22:49:14 +05:30
|
|
|
this.state = {
|
2024-09-09 19:06:03 +05:30
|
|
|
zIndex: 0,
|
|
|
|
|
selected: false,
|
2024-09-15 12:08:29 +05:30
|
|
|
widgetName: widgetName || 'widget', // this will later be converted to variable name
|
2024-09-13 12:28:32 +05:30
|
|
|
enableRename: false, // will open the widgets editable div for renaming
|
2024-09-10 21:34:05 +05:30
|
|
|
resizing: false,
|
2024-09-13 19:24:03 +05:30
|
|
|
resizeCorner: "",
|
2024-09-17 18:32:33 +05:30
|
|
|
dragEnabled: true,
|
|
|
|
|
|
|
|
|
|
showDroppableStyle: { // shows the droppable indicator
|
|
|
|
|
allow: false,
|
|
|
|
|
show: false,
|
|
|
|
|
},
|
2024-09-13 19:24:03 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
pos: { x: 0, y: 0 },
|
|
|
|
|
size: { width: 100, height: 100 },
|
2024-09-14 16:03:26 +05:30
|
|
|
position: "absolute",
|
|
|
|
|
|
2024-09-13 22:05:38 +05:30
|
|
|
widgetStyling: {
|
2024-09-14 16:03:26 +05:30
|
|
|
// use for widget's inner styling
|
2024-09-13 22:05:38 +05:30
|
|
|
},
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
attrs: {
|
2024-09-13 19:24:03 +05:30
|
|
|
styling: {
|
|
|
|
|
backgroundColor: {
|
2024-09-14 16:03:26 +05:30
|
|
|
label: "Background Color",
|
2024-09-13 19:24:03 +05:30
|
|
|
tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string
|
2024-09-13 22:05:38 +05:30
|
|
|
value: "",
|
2024-09-16 22:04:24 +05:30
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setWidgetStyling("backgroundColor", value)
|
|
|
|
|
this.setAttrValue("styling.backgroundColor", value)
|
|
|
|
|
}
|
2024-09-13 19:24:03 +05:30
|
|
|
},
|
|
|
|
|
foregroundColor: {
|
2024-09-14 16:03:26 +05:30
|
|
|
label: "Foreground Color",
|
2024-09-13 19:24:03 +05:30
|
|
|
tool: Tools.COLOR_PICKER,
|
2024-09-14 16:03:26 +05:30
|
|
|
value: "",
|
|
|
|
|
},
|
2024-09-15 12:08:29 +05:30
|
|
|
label: "Styling"
|
2024-09-14 16:03:26 +05:30
|
|
|
},
|
|
|
|
|
layout: {
|
|
|
|
|
label: "Layout",
|
|
|
|
|
tool: Tools.SELECT_DROPDOWN, // the tool to display, can be either HTML ELement or a constant string
|
|
|
|
|
value: "flex",
|
|
|
|
|
options: [
|
2024-09-15 12:08:29 +05:30
|
|
|
{ value: "flex", label: "Flex" },
|
|
|
|
|
{ value: "grid", label: "Grid" },
|
|
|
|
|
{ value: "place", label: "Place" },
|
2024-09-14 16:03:26 +05:30
|
|
|
],
|
2024-09-15 12:08:29 +05:30
|
|
|
onChange: (value) => this.setWidgetStyling("backgroundColor", value)
|
2024-09-13 19:24:03 +05:30
|
|
|
},
|
|
|
|
|
events: {
|
|
|
|
|
event1: {
|
|
|
|
|
tool: Tools.EVENT_HANDLER,
|
|
|
|
|
value: ""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-08-08 22:49:14 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-09 19:06:03 +05:30
|
|
|
this.mousePress = this.mousePress.bind(this)
|
|
|
|
|
this.getElement = this.getElement.bind(this)
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
this.getPos = this.getPos.bind(this)
|
|
|
|
|
this.getSize = this.getSize.bind(this)
|
2024-09-13 16:03:58 +05:30
|
|
|
this.getWidgetName = this.getWidgetName.bind(this)
|
|
|
|
|
this.getWidgetType = this.getWidgetType.bind(this)
|
2024-09-15 12:08:29 +05:30
|
|
|
this.getBoundingRect = this.getBoundingRect.bind(this)
|
|
|
|
|
|
|
|
|
|
this.getToolbarAttrs = this.getToolbarAttrs.bind(this)
|
|
|
|
|
|
2024-09-13 12:28:32 +05:30
|
|
|
// this.openRenaming = this.openRenaming.bind(this)
|
|
|
|
|
|
2024-09-09 19:06:03 +05:30
|
|
|
this.isSelected = this.isSelected.bind(this)
|
|
|
|
|
|
|
|
|
|
this.setPos = this.setPos.bind(this)
|
2024-09-15 12:08:29 +05:30
|
|
|
this.setAttrValue = this.setAttrValue.bind(this)
|
|
|
|
|
this.setWidgetName = this.setWidgetName.bind(this)
|
2024-09-13 22:05:38 +05:30
|
|
|
this.setWidgetStyling = this.setWidgetStyling.bind(this)
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-09-10 21:34:05 +05:30
|
|
|
this.startResizing = this.startResizing.bind(this)
|
|
|
|
|
this.handleResize = this.handleResize.bind(this)
|
|
|
|
|
this.stopResizing = this.stopResizing.bind(this)
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
}
|
2024-08-08 16:21:19 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
componentDidMount() {
|
2024-08-08 22:49:14 +05:30
|
|
|
this.elementRef.current?.addEventListener("click", this.mousePress)
|
2024-09-10 21:34:05 +05:30
|
|
|
|
2024-09-13 22:05:38 +05:30
|
|
|
this.canvas.addEventListener("mousemove", this.handleResize)
|
2024-09-10 21:34:05 +05:30
|
|
|
this.canvas.addEventListener("mouseup", this.stopResizing)
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
componentWillUnmount() {
|
2024-08-08 22:49:14 +05:30
|
|
|
this.elementRef.current?.removeEventListener("click", this.mousePress)
|
2024-09-10 21:34:05 +05:30
|
|
|
|
2024-09-13 22:05:38 +05:30
|
|
|
this.canvas.addEventListener("mousemove", this.handleResize)
|
2024-09-10 21:34:05 +05:30
|
|
|
this.canvas.addEventListener("mouseup", this.stopResizing)
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-16 22:04:24 +05:30
|
|
|
componentDidUpdate(prevProps, prevState) {
|
|
|
|
|
// if (prevState !== this.state) {
|
|
|
|
|
// // State has changed
|
|
|
|
|
// console.log('State has been updated')
|
|
|
|
|
// } else {
|
|
|
|
|
// // State has not changed
|
|
|
|
|
// console.log('State has not changed')
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
updateState = (newState, callback) => {
|
2024-09-16 22:04:24 +05:30
|
|
|
|
|
|
|
|
// FIXME: maximum recursion error when updating size
|
2024-09-15 12:08:29 +05:30
|
|
|
this.setState(newState, () => {
|
2024-09-16 22:04:24 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
const { onWidgetUpdate } = this.props
|
|
|
|
|
if (onWidgetUpdate) {
|
|
|
|
|
onWidgetUpdate(this.__id)
|
|
|
|
|
}
|
2024-09-16 22:04:24 +05:30
|
|
|
|
|
|
|
|
// const { activeWidgetId, updateToolAttrs } = this.context
|
|
|
|
|
|
|
|
|
|
// if (activeWidgetId === this.__id)
|
|
|
|
|
// updateToolAttrs(this.getToolbarAttrs())
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
if (callback) callback()
|
2024-09-16 22:04:24 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_getWidgetMethods = () => {
|
|
|
|
|
return {
|
|
|
|
|
rename: this.setWidgetName,
|
|
|
|
|
resize: this.setWidgetSize,
|
|
|
|
|
setWidgetAttrs: this.setAttrValue,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getToolbarAttrs(){
|
|
|
|
|
|
|
|
|
|
return ({
|
|
|
|
|
widgetName: {
|
|
|
|
|
label: "Widget Name",
|
|
|
|
|
tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string
|
|
|
|
|
toolProps: {placeholder: "Widget name", maxLength: 40},
|
|
|
|
|
value: this.state.widgetName,
|
|
|
|
|
onChange: (value) => this.setWidgetName(value)
|
|
|
|
|
},
|
|
|
|
|
size: {
|
2024-09-16 22:04:24 +05:30
|
|
|
label: "Size",
|
2024-09-15 12:08:29 +05:30
|
|
|
display: "horizontal",
|
|
|
|
|
width: {
|
|
|
|
|
label: "Width",
|
|
|
|
|
tool: Tools.NUMBER_INPUT, // the tool to display, can be either HTML ELement or a constant string
|
|
|
|
|
toolProps: {placeholder: "width", max: this.maxSize.width, min: this.minSize.width},
|
|
|
|
|
value: this.state.size.width || 100,
|
|
|
|
|
onChange: (value) => this.setWidgetSize(value, null)
|
|
|
|
|
},
|
|
|
|
|
height: {
|
|
|
|
|
label: "Height",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
2024-09-15 15:31:04 +05:30
|
|
|
toolProps: {placeholder: "height", max: this.maxSize.height, min: this.minSize.height},
|
2024-09-15 12:08:29 +05:30
|
|
|
value: this.state.size.height || 100,
|
|
|
|
|
onChange: (value) => this.setWidgetSize(null, value)
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
...this.state.attrs,
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-09 19:06:03 +05:30
|
|
|
// TODO: add context menu items such as delete, add etc
|
2024-09-15 12:08:29 +05:30
|
|
|
contextMenu() {
|
|
|
|
|
|
2024-09-09 19:06:03 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getVariableName() {
|
2024-09-09 19:06:03 +05:30
|
|
|
return toSnakeCase(this.state.widgetName)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getWidgetName() {
|
2024-09-13 16:03:58 +05:30
|
|
|
return this.state.widgetName
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getWidgetType() {
|
2024-09-13 16:03:58 +05:30
|
|
|
return this.constructor.widgetType
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getAttributes() {
|
2024-09-13 19:24:03 +05:30
|
|
|
return this.state.attrs
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-12 19:20:46 +05:30
|
|
|
/**
|
|
|
|
|
* removes the element/widget
|
|
|
|
|
*/
|
2024-09-15 12:08:29 +05:30
|
|
|
remove() {
|
|
|
|
|
this.canvas.removeWidget(this.__id)
|
2024-09-12 19:20:46 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
mousePress(event) {
|
2024-09-09 19:06:03 +05:30
|
|
|
// event.preventDefault()
|
2024-09-15 12:08:29 +05:30
|
|
|
if (!this._disableSelection) {
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
select() {
|
2024-09-09 19:24:43 +05:30
|
|
|
this.setState({
|
2024-09-09 19:06:03 +05:30
|
|
|
selected: true
|
2024-09-09 19:24:43 +05:30
|
|
|
})
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
deSelect() {
|
2024-09-09 19:24:43 +05:30
|
|
|
this.setState({
|
2024-09-09 19:06:03 +05:30
|
|
|
selected: false
|
2024-09-09 19:24:43 +05:30
|
|
|
})
|
2024-09-09 19:06:03 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
isSelected() {
|
2024-09-09 19:06:03 +05:30
|
|
|
return this.state.selected
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
setPos(x, y) {
|
2024-09-10 21:34:05 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
if (this.state.resizing) {
|
2024-09-10 21:34:05 +05:30
|
|
|
// don't change position when resizing the widget
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-09-12 19:20:46 +05:30
|
|
|
|
2024-09-16 22:04:24 +05:30
|
|
|
this.setState({
|
2024-09-15 12:08:29 +05:30
|
|
|
pos: { x, y }
|
|
|
|
|
})
|
2024-09-16 22:04:24 +05:30
|
|
|
|
|
|
|
|
// this.updateState({
|
|
|
|
|
// pos: { x, y }
|
|
|
|
|
// })
|
2024-09-12 22:09:13 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
setParent(parentId) {
|
2024-09-12 22:09:13 +05:30
|
|
|
this._parent = parentId
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
addChild(childId) {
|
2024-09-12 22:09:13 +05:30
|
|
|
this._children.push(childId)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
removeChild(childId) {
|
|
|
|
|
this._children = this._children.filter(function (item) {
|
|
|
|
|
return item !== childId
|
|
|
|
|
})
|
2024-09-09 19:06:03 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getPos() {
|
2024-09-14 16:03:26 +05:30
|
|
|
return this.state.pos
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getProps() {
|
2024-09-09 19:06:03 +05:30
|
|
|
return this.attrs
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getBoundingRect() {
|
2024-09-10 21:34:05 +05:30
|
|
|
return this.elementRef.current?.getBoundingClientRect()
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getSize() {
|
|
|
|
|
return this.state.size
|
2024-09-10 21:34:05 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getWidgetFunctions() {
|
2024-08-08 16:21:19 +05:30
|
|
|
return this.functions
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getId() {
|
2024-08-08 16:21:19 +05:30
|
|
|
return this.__id
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
getElement() {
|
2024-09-09 19:06:03 +05:30
|
|
|
return this.elementRef.current
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
/**
|
|
|
|
|
* Given the key as a path, sets the value for the widget attribute
|
|
|
|
|
* @param {string} path - path to the key, eg: styling.backgroundColor
|
|
|
|
|
* @param {any} value
|
|
|
|
|
*/
|
2024-09-15 12:08:29 +05:30
|
|
|
setAttrValue(path, value) {
|
2024-09-14 16:03:26 +05:30
|
|
|
this.setState((prevState) => {
|
|
|
|
|
// Split the path to access the nested property (e.g., "styling.backgroundColor")
|
|
|
|
|
const keys = path.split('.')
|
|
|
|
|
const lastKey = keys.pop()
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
// Traverse the state and update the nested value immutably
|
|
|
|
|
let newAttrs = { ...prevState.attrs }
|
|
|
|
|
let nestedObject = newAttrs
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
keys.forEach(key => {
|
|
|
|
|
nestedObject[key] = { ...nestedObject[key] } // Ensure immutability
|
|
|
|
|
nestedObject = nestedObject[key]
|
|
|
|
|
})
|
|
|
|
|
nestedObject[lastKey].value = value
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
return { attrs: newAttrs }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 21:34:05 +05:30
|
|
|
startResizing(corner, event) {
|
|
|
|
|
event.stopPropagation()
|
|
|
|
|
this.setState({ resizing: true, resizeCorner: corner })
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
setZIndex(zIndex) {
|
2024-09-13 12:28:32 +05:30
|
|
|
this.setState({
|
|
|
|
|
zIndex: zIndex
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
setWidgetName(name) {
|
2024-09-14 16:03:26 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
// this.setState((prev) => ({
|
|
|
|
|
// widgetName: name.length > 0 ? name : prev.widgetName
|
|
|
|
|
// }))
|
|
|
|
|
|
|
|
|
|
this.updateState({
|
|
|
|
|
widgetName: name.length > 0 ? name : this.state.widgetName
|
|
|
|
|
})
|
2024-09-14 16:03:26 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param {string} key - The string in react Style format
|
|
|
|
|
* @param {string} value - Value of the style
|
|
|
|
|
* @param {function():void} [callback] - optional callback, thats called after setting the internal state
|
|
|
|
|
*/
|
2024-09-16 22:04:24 +05:30
|
|
|
setWidgetStyling(key, value) {
|
2024-09-15 12:08:29 +05:30
|
|
|
|
|
|
|
|
const widgetStyle = {
|
|
|
|
|
...this.state.widgetStyling,
|
|
|
|
|
[key]: value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
|
widgetStyling: widgetStyle
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param {number|null} width
|
|
|
|
|
* @param {number|null} height
|
|
|
|
|
*/
|
2024-09-16 22:04:24 +05:30
|
|
|
setWidgetSize(width, height) {
|
2024-09-15 12:08:29 +05:30
|
|
|
|
|
|
|
|
const newSize = {
|
|
|
|
|
width: Math.max(this.minSize.width, Math.min(width || this.state.size.width, this.maxSize.width)),
|
|
|
|
|
height: Math.max(this.minSize.height, Math.min(height || this.state.size.height, this.maxSize.height)),
|
|
|
|
|
}
|
|
|
|
|
this.updateState({
|
|
|
|
|
size: newSize
|
|
|
|
|
})
|
2024-09-14 16:03:26 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-10 21:34:05 +05:30
|
|
|
handleResize(event) {
|
|
|
|
|
if (!this.state.resizing) return
|
|
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
const { resizeCorner, size, pos } = this.state
|
2024-09-10 21:34:05 +05:30
|
|
|
const deltaX = event.movementX
|
|
|
|
|
const deltaY = event.movementY
|
|
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
let newSize = { ...size }
|
|
|
|
|
let newPos = { ...pos }
|
2024-09-15 12:08:29 +05:30
|
|
|
|
|
|
|
|
const { width: minWidth, height: minHeight } = this.minSize
|
|
|
|
|
const { width: maxWidth, height: maxHeight } = this.maxSize
|
2024-09-14 16:03:26 +05:30
|
|
|
// console.log("resizing: ", deltaX, deltaY, event)
|
2024-09-10 21:34:05 +05:30
|
|
|
|
|
|
|
|
switch (resizeCorner) {
|
|
|
|
|
case "nw":
|
|
|
|
|
newSize.width = Math.max(minWidth, Math.min(maxWidth, newSize.width - deltaX))
|
|
|
|
|
newSize.height = Math.max(minHeight, Math.min(maxHeight, newSize.height - deltaY))
|
2024-09-14 16:03:26 +05:30
|
|
|
newPos.x += (newSize.width !== size.width) ? deltaX : 0
|
|
|
|
|
newPos.y += (newSize.height !== size.height) ? deltaY : 0
|
2024-09-10 21:34:05 +05:30
|
|
|
break
|
|
|
|
|
case "ne":
|
|
|
|
|
newSize.width = Math.max(minWidth, Math.min(maxWidth, newSize.width + deltaX))
|
|
|
|
|
newSize.height = Math.max(minHeight, Math.min(maxHeight, newSize.height - deltaY))
|
2024-09-14 16:03:26 +05:30
|
|
|
newPos.y += (newSize.height !== size.height) ? deltaY : 0
|
2024-09-10 21:34:05 +05:30
|
|
|
break
|
|
|
|
|
case "sw":
|
|
|
|
|
newSize.width = Math.max(minWidth, Math.min(maxWidth, newSize.width - deltaX))
|
|
|
|
|
newSize.height = Math.max(minHeight, Math.min(maxHeight, newSize.height + deltaY))
|
2024-09-14 16:03:26 +05:30
|
|
|
newPos.x += (newSize.width !== size.width) ? deltaX : 0
|
2024-09-10 21:34:05 +05:30
|
|
|
break
|
|
|
|
|
case "se":
|
|
|
|
|
newSize.width = Math.max(minWidth, Math.min(maxWidth, newSize.width + deltaX))
|
|
|
|
|
newSize.height = Math.max(minHeight, Math.min(maxHeight, newSize.height + deltaY))
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
// this.setState({ size: newSize, pos: newPos })
|
|
|
|
|
this.updateState({
|
|
|
|
|
size: newSize,
|
|
|
|
|
pos: newPos
|
|
|
|
|
})
|
2024-09-10 21:34:05 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stopResizing() {
|
|
|
|
|
if (this.state.resizing) {
|
|
|
|
|
this.setState({ resizing: false })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
openRenaming() {
|
2024-09-13 12:28:32 +05:30
|
|
|
this.setState({
|
|
|
|
|
selected: true,
|
|
|
|
|
enableRename: true
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
closeRenaming() {
|
2024-09-13 12:28:32 +05:30
|
|
|
this.setState({
|
|
|
|
|
enableRename: false
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-17 18:32:33 +05:30
|
|
|
handleDrop = (event, dragElement) => {
|
|
|
|
|
console.log("dragging event: ", event, dragElement)
|
|
|
|
|
|
|
|
|
|
const container = dragElement.getAttribute("data-container")
|
|
|
|
|
|
|
|
|
|
if (container === "canvas"){
|
|
|
|
|
|
|
|
|
|
// this.canvas.getWidgetById
|
|
|
|
|
|
|
|
|
|
// this._children.push()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 15:31:04 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
renderContent() {
|
2024-08-08 16:21:19 +05:30
|
|
|
// throw new NotImplementedError("render method has to be implemented")
|
|
|
|
|
return (
|
2024-09-14 16:03:26 +05:30
|
|
|
<div className="tw-w-full tw-h-full tw-rounded-md tw-bg-red-500" style={this.state.widgetStyling}>
|
2024-08-08 16:21:19 +05:30
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 15:31:04 +05:30
|
|
|
|
2024-08-08 16:21:19 +05:30
|
|
|
/**
|
|
|
|
|
* This is an internal methods don't override
|
|
|
|
|
* @returns {HTMLElement}
|
|
|
|
|
*/
|
2024-09-15 12:08:29 +05:30
|
|
|
render() {
|
|
|
|
|
|
2024-09-14 16:03:26 +05:30
|
|
|
let outerStyle = {
|
2024-08-08 16:21:19 +05:30
|
|
|
cursor: this.cursor,
|
2024-09-13 12:28:32 +05:30
|
|
|
zIndex: this.state.zIndex,
|
|
|
|
|
position: "absolute", // don't change this if it has to be movable on the canvas
|
2024-09-15 12:08:29 +05:30
|
|
|
top: `${this.state.pos.y}px`,
|
|
|
|
|
left: `${this.state.pos.x}px`,
|
2024-09-14 16:03:26 +05:30
|
|
|
width: `${this.state.size.width}px`,
|
|
|
|
|
height: `${this.state.size.height}px`,
|
2024-08-08 16:21:19 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-17 18:32:33 +05:30
|
|
|
// console.log("Drag enabled: ", this.state.dragEnabled)
|
2024-09-13 12:28:32 +05:30
|
|
|
// console.log("selected: ", this.state.selected)
|
2024-08-08 16:21:19 +05:30
|
|
|
return (
|
2024-09-17 18:32:33 +05:30
|
|
|
<WidgetDraggable widgetRef={this.elementRef}
|
|
|
|
|
enableDrag={this.state.dragEnabled}
|
|
|
|
|
onDrop={this.handleDrop}
|
|
|
|
|
onDragEnter={({dragElement, showDrop}) => {
|
|
|
|
|
this.setState({
|
|
|
|
|
showDroppableStyle: showDrop
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
onDragLeave={ () => {
|
|
|
|
|
this.setState({
|
|
|
|
|
showDroppableStyle: {
|
|
|
|
|
allow: false,
|
|
|
|
|
show: false
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
|
2024-09-17 11:55:21 +05:30
|
|
|
<div data-widget-id={this.__id}
|
|
|
|
|
ref={this.elementRef}
|
|
|
|
|
className="tw-absolute tw-shadow-xl tw-w-fit tw-h-fit"
|
2024-09-16 22:04:24 +05:30
|
|
|
style={outerStyle}
|
2024-09-17 11:55:21 +05:30
|
|
|
data-draggable-type={this.getWidgetType()} // helps with droppable
|
|
|
|
|
data-container={"canvas"} // indicates how the canvas should handle dragging, one is sidebar other is canvas
|
2024-09-16 22:04:24 +05:30
|
|
|
>
|
|
|
|
|
|
|
|
|
|
{this.renderContent()}
|
2024-09-17 18:32:33 +05:30
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// show drop style on drag hover
|
|
|
|
|
this.state.showDroppableStyle.show &&
|
|
|
|
|
<div className={`${this.state.showDroppableStyle.allow ? "tw-border-blue-600" : "tw-border-red-600"}
|
|
|
|
|
tw-absolute tw-top-[-5px] tw-left-[-5px] tw-w-full tw-h-full tw-z-[2]
|
|
|
|
|
tw-border-2 tw-border-dashed tw-rounded-lg tw-pointer-events-none
|
|
|
|
|
|
|
|
|
|
`}
|
|
|
|
|
style={
|
|
|
|
|
{
|
|
|
|
|
width: "calc(100% + 10px)",
|
|
|
|
|
height: "calc(100% + 10px)",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-16 22:04:24 +05:30
|
|
|
<div className={`tw-absolute tw-bg-transparent tw-scale-[1.1] tw-opacity-100
|
|
|
|
|
tw-w-full tw-h-full tw-top-0
|
|
|
|
|
${this.state.selected ? 'tw-border-2 tw-border-solid tw-border-blue-500' : 'tw-hidden'}`}>
|
|
|
|
|
|
|
|
|
|
<div className="tw-relative tw-w-full tw-h-full">
|
|
|
|
|
<EditableDiv value={this.state.widgetName} onChange={this.setWidgetName}
|
|
|
|
|
maxLength={40}
|
|
|
|
|
openEdit={this.state.enableRename}
|
|
|
|
|
className="tw-text-sm tw-w-fit tw-max-w-[160px] tw-text-clip tw-min-w-[150px]
|
|
|
|
|
tw-overflow-hidden tw-absolute tw--top-6 tw-h-6"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
className="tw-w-2 tw-h-2 tw-absolute tw--left-1 tw--top-1 tw-bg-blue-500"
|
|
|
|
|
style={{ cursor: Cursor.NW_RESIZE }}
|
2024-09-17 18:32:33 +05:30
|
|
|
onMouseDown={(e) => {
|
|
|
|
|
this.startResizing("nw", e)
|
|
|
|
|
this.setState({dragEnabled: false})
|
|
|
|
|
}}
|
|
|
|
|
onMouseLeave={() => this.setState({dragEnabled: true})}
|
2024-09-16 22:04:24 +05:30
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
className="tw-w-2 tw-h-2 tw-absolute tw--right-1 tw--top-1 tw-bg-blue-500"
|
|
|
|
|
style={{ cursor: Cursor.SW_RESIZE }}
|
2024-09-17 18:32:33 +05:30
|
|
|
onMouseDown={(e) => {
|
|
|
|
|
this.startResizing("ne", e)
|
|
|
|
|
this.setState({dragEnabled: false})
|
|
|
|
|
}}
|
|
|
|
|
onMouseLeave={() => this.setState({dragEnabled: true})}
|
2024-09-16 22:04:24 +05:30
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
className="tw-w-2 tw-h-2 tw-absolute tw--left-1 tw--bottom-1 tw-bg-blue-500"
|
|
|
|
|
style={{ cursor: Cursor.SW_RESIZE }}
|
2024-09-17 18:32:33 +05:30
|
|
|
onMouseDown={(e) => {
|
|
|
|
|
this.startResizing("sw", e)
|
|
|
|
|
this.setState({dragEnabled: false})
|
|
|
|
|
}}
|
|
|
|
|
onMouseLeave={() => this.setState({dragEnabled: true})}
|
2024-09-16 22:04:24 +05:30
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
className="tw-w-2 tw-h-2 tw-absolute tw--right-1 tw--bottom-1 tw-bg-blue-500"
|
|
|
|
|
style={{ cursor: Cursor.SE_RESIZE }}
|
2024-09-17 18:32:33 +05:30
|
|
|
onMouseDown={(e) => {
|
|
|
|
|
this.startResizing("se", e)
|
|
|
|
|
this.setState({dragEnabled: false})
|
|
|
|
|
}}
|
|
|
|
|
onMouseLeave={() => this.setState({dragEnabled: true})}
|
2024-09-16 22:04:24 +05:30
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
</div>
|
2024-08-08 16:21:19 +05:30
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
|
2024-09-09 19:06:03 +05:30
|
|
|
|
2024-09-16 22:04:24 +05:30
|
|
|
</div>
|
2024-08-08 16:21:19 +05:30
|
|
|
</div>
|
2024-09-17 11:55:21 +05:30
|
|
|
</WidgetDraggable>
|
2024-08-08 16:21:19 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 12:08:29 +05:30
|
|
|
}
|
2024-08-08 16:21:19 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
export default Widget
|