added MainWindow widget and updated readme

This commit is contained in:
paul
2024-09-22 19:23:06 +05:30
parent d942663b39
commit 65d7aec1a2
14 changed files with 210 additions and 33 deletions

View File

@@ -713,6 +713,8 @@ class Canvas extends React.Component {
throw new Error("widgetComponentType must be a subclass of Widget class")
}
console.log("componete: ", widgetComponentType)
const widgetRef = React.createRef()
const id = `${widgetComponentType.widgetType}_${UID()}`
@@ -842,7 +844,7 @@ class Canvas extends React.Component {
// TODO: handle drop from sidebar
// if the widget is being dropped from the sidebar, use the info to create the widget first
this.createWidget(Widget, ({ id, widgetRef }) => {
this.createWidget(widgetClass, ({ id, widgetRef }) => {
widgetRef.current.setPos(finalPosition.x, finalPosition.y)
})
@@ -968,6 +970,7 @@ class Canvas extends React.Component {
{/* <ActiveWidgetProvider> */}
<DroppableWrapper id="canvas-droppable"
droppableTags={{exclude: ["image", "video"]}}
className="tw-w-full tw-h-full"
onDrop={this.handleDropEvent}>
{/* <DragWidgetProvider> */}

View File

@@ -55,7 +55,7 @@ class Widget extends React.Component {
"load": { "args1": "number", "args2": "string" }
}
this.droppableTags = ["widget"] // This indicates if the draggable can be dropped on this widget
this.droppableTags = {} // This indicates if the draggable can be dropped on this widget
this.boundingRect = {
x: 0,
y: 0,
@@ -143,7 +143,6 @@ class Widget extends React.Component {
},
}
this.mousePress = this.mousePress.bind(this)
this.getElement = this.getElement.bind(this)
this.getId = this.getId.bind(this)
@@ -169,7 +168,6 @@ class Widget extends React.Component {
}
componentDidMount() {
this.elementRef.current?.addEventListener("click", this.mousePress)
// FIXME: initial layout is not set properly
console.log("prior layout: ", this.state.attrs.layout.value)
@@ -182,7 +180,6 @@ class Widget extends React.Component {
}
componentWillUnmount() {
this.elementRef.current?.removeEventListener("click", this.mousePress)
}
updateState = (newState, callback) => {
@@ -273,12 +270,6 @@ class Widget extends React.Component {
return this.__id
}
mousePress(event) {
// event.preventDefault()
if (!this._disableSelection) {
}
}
select() {
this.setState({
selected: true
@@ -642,7 +633,12 @@ class Widget extends React.Component {
show: true
}
if (this.droppableTags.length === 0 || this.droppableTags.includes(dragEleType)) {
const allowDrop = (this.droppableTags && (Object.keys(this.droppableTags).length === 0 ||
(this.droppableTags.include?.length > 0 && this.droppableTags.include?.includes(dragEleType)) ||
(this.droppableTags.exclude?.length > 0 && !this.droppableTags.exclude?.includes(dragEleType))
))
if (allowDrop) {
showDrop = {
allow: true,
show: true
@@ -670,7 +666,12 @@ class Widget extends React.Component {
// console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer)
const dragEleType = draggedElement.getAttribute("data-draggable-type")
if (this.droppableTags.length === 0 || this.droppableTags.includes(dragEleType)) {
const allowDrop = (this.droppableTags && (Object.keys(this.droppableTags).length === 0 ||
(this.droppableTags.include?.length > 0 && this.droppableTags.include?.includes(dragEleType)) ||
(this.droppableTags.exclude?.length > 0 && !this.droppableTags.exclude?.includes(dragEleType))
))
if (allowDrop) {
e.preventDefault() // NOTE: this is necessary to allow drop to take place
}
@@ -692,7 +693,12 @@ class Widget extends React.Component {
const dragEleType = draggedElement.getAttribute("data-draggable-type")
if (this.droppableTags.length > 0 && !this.droppableTags.includes(dragEleType)) {
const allowDrop = (this.droppableTags && (Object.keys(this.droppableTags).length === 0 ||
(this.droppableTags.include?.length > 0 && this.droppableTags.include?.includes(dragEleType)) ||
(this.droppableTags.exclude?.length > 0 && !this.droppableTags.exclude?.includes(dragEleType))
))
if (allowDrop) {
return // prevent drop if the draggable element doesn't match
}
@@ -771,11 +777,14 @@ class Widget extends React.Component {
this.elementRef.current.style.pointerEvents = "auto"
}
// FIXME: children outside the bounding box, add tw-overflow-hidden
renderContent() {
/**
* Note: you must implement this method in subclass, if you want children make sure to pass
* {this.props.children}, to modify the style add this.state.widgetStyling
*/
renderContent() {
// throw new NotImplementedError("render method has to be implemented")
return (
<div className="tw-w-full tw-h-full tw-p-2 tw-content-start tw-rounded-md" style={this.state.widgetStyling}>
<div className="tw-w-full tw-h-full tw-p-2 tw-content-start tw-rounded-md tw-overflow-hidden" style={this.state.widgetStyling}>
{this.props.children}
</div>
)

View File

@@ -14,7 +14,7 @@ import { useDragContext } from "../../components/draggable/draggableContext"
*/
const WidgetDraggable = memo(({ widgetRef, enableDrag=true, dragElementType="widget",
onDragEnter, onDragLeave, onDrop, style={},
droppableTags = ["widget"], ...props }) => {
droppableTags = {}, ...props }) => {
// const { draggedElement, onDragStart, onDragEnd } = useDragWidgetContext()
const { draggedElement, onDragStart, onDragEnd, overElement, setOverElement } = useDragContext()
@@ -71,8 +71,12 @@ const WidgetDraggable = memo(({ widgetRef, enableDrag=true, dragElementType="wid
allow: true,
show: true
}
const allowDrop = (Object.keys(droppableTags).length === 0 ||
(droppableTags.include.length > 0 && droppableTags.include.includes(dragEleType)) ||
(droppableTags.exclude.length > 0 && !droppableTags.exclude.includes(dragEleType))
)
if (droppableTags.length === 0 || droppableTags.includes(dragEleType)) {
if (allowDrop) {
showDrop = {
allow: true,
show: true
@@ -99,7 +103,12 @@ const WidgetDraggable = memo(({ widgetRef, enableDrag=true, dragElementType="wid
// console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer)
const dragEleType = draggedElement.getAttribute("data-draggable-type")
if (droppableTags.length === 0 || droppableTags.includes(dragEleType)) {
const allowDrop = (Object.keys(droppableTags).length === 0 ||
(droppableTags.include.length > 0 && droppableTags.include.includes(dragEleType)) ||
(droppableTags.exclude.length > 0 && !droppableTags.exclude.includes(dragEleType))
)
if (allowDrop) {
e.preventDefault() // this is necessary to allow drop to take place
}

View File

@@ -2,7 +2,10 @@ import { memo, useState } from "react"
import { useDragContext } from "./draggableContext"
const DroppableWrapper = memo(({onDrop, droppableTags=["widget"], ...props}) => {
/**
* @param {{include: [], exclude: []} || {}} - droppableTags - if empty object, allows everything to be dropped, define include to allow only included widgets, define exclude to exclude
*/
const DroppableWrapper = memo(({onDrop, droppableTags={}, ...props}) => {
const { draggedElement, overElement, setOverElement, widgetClass } = useDragContext()
@@ -17,11 +20,16 @@ const DroppableWrapper = memo(({onDrop, droppableTags=["widget"], ...props}) =>
const dragElementType = draggedElement.getAttribute("data-draggable-type")
// console.log("Current target: ", e.currentTarget)
console.log("Current target: ", droppableTags, Object.keys(droppableTags))
setOverElement(e.currentTarget)
if (droppableTags.length === 0 || droppableTags.includes(dragElementType)){
const allowDrop = (droppableTags && (Object.keys(droppableTags).length === 0 ||
(droppableTags.include?.length > 0 && droppableTags.include?.includes(dragElementType)) ||
(droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType))
))
if (allowDrop){
setShowDroppable({
allow: true,
show: true
@@ -37,8 +45,13 @@ const DroppableWrapper = memo(({onDrop, droppableTags=["widget"], ...props}) =>
const handleDragOver = (e) => {
// console.log("Drag over: ", e.dataTransfer.getData("text/plain"), e.dataTransfer)
const dragElementType = draggedElement.getAttribute("data-draggable-type")
if (droppableTags.length === 0 || droppableTags.includes(dragElementType)){
const allowDrop = (droppableTags && (Object.keys(droppableTags).length === 0 ||
(droppableTags.include?.length > 0 && droppableTags.include?.includes(dragElementType)) ||
(droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType))
))
if (allowDrop){
e.preventDefault() // this is necessary to allow drop to take place
}
@@ -51,8 +64,15 @@ const DroppableWrapper = memo(({onDrop, droppableTags=["widget"], ...props}) =>
allow: false,
show: false
})
const dragElementType = draggedElement.getAttribute("data-draggable-type")
if(onDrop){
const allowDrop = (droppableTags && (Object.keys(droppableTags).length === 0 ||
(droppableTags.include?.length > 0 && droppableTags.include?.includes(dragElementType)) ||
(droppableTags.exclude?.length > 0 && !droppableTags.exclude?.includes(dragElementType))
))
if(onDrop && allowDrop){
onDrop(e, draggedElement, widgetClass)
}
}

View File

@@ -2,6 +2,7 @@
import Widget from "../../canvas/widgets/base"
import ButtonWidget from "./assets/widgets/button.png"
import MainWindow from "./widgets/mainWindow"
const TkinterSidebar = [
@@ -9,7 +10,7 @@ const TkinterSidebar = [
name: "Main window",
img: ButtonWidget,
link: "https://github.com",
widgetClass: Widget
widgetClass: MainWindow
},
{
name: "Top Level",

View File

@@ -0,0 +1,46 @@
import { CloseCircleFilled, ExpandOutlined, MinusCircleFilled } from "@ant-design/icons"
import Widget from "../../../canvas/widgets/base"
class MainWindow extends Widget{
static widgetType = "main_window"
constructor(props) {
super(props)
this.droppableTags = {
exclude: ["image", "video", "media"]
}
this.state = {
...this.state,
}
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
}
renderContent(){
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="tw-flex tw-w-full tw-h-[25px] tw-bg-[#adadad] tw-shadow-md">
<div className="tw-ml-auto tw-flex tw-gap-1 tw-p-1 tw-place-items-center">
<div className="tw-bg-yellow-400 tw-rounded-full tw-w-[15px] tw-h-[15px]">
</div>
<div className="tw-bg-blue-400 tw-rounded-full tw-w-[15px] tw-h-[15px]">
</div>
<div className="tw-bg-red-400 tw-rounded-full tw-w-[15px] tw-h-[15px]">
</div>
</div>
</div>
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start" style={this.state.widgetStyling}>
{this.props.children}
</div>
</div>
)
}
}
export default MainWindow

View File

@@ -11,7 +11,7 @@ function Share({children, className=""}){
const shareInfo = useMemo(() => {
return {
url: encodeURI("https://github.com/PaulleDemon/font-tester-chrome"),
url: encodeURI("https://github.com/PaulleDemon/tkbuilder"),
text: "Check out Framework agnostic GUI builder for python"
}
}, [])