Files
PyUIBuilder/src/App.js

276 lines
8.9 KiB
JavaScript
Raw Normal View History

2024-10-01 11:22:45 +05:30
/**
* Author: Paul
* Github: PaulleDemon
*/
import { useEffect, useRef, useState } from 'react'
2024-08-04 22:47:43 +05:30
2025-03-08 20:11:22 +05:30
import { LayoutFilled, ProductFilled, CloudUploadOutlined, DatabaseFilled, AlignLeftOutlined } from "@ant-design/icons"
2024-09-26 11:59:24 +05:30
// import { DndContext, useSensors, useSensor, PointerSensor, closestCorners, DragOverlay, rectIntersection } from '@dnd-kit/core'
// import { snapCenterToCursor } from '@dnd-kit/modifiers'
2024-08-04 22:47:43 +05:30
2024-08-08 16:21:19 +05:30
import Canvas from './canvas/canvas'
2024-09-08 21:58:53 +05:30
import Header from './components/header'
2024-09-14 16:03:26 +05:30
import Sidebar from './sidebar/sidebar'
import UploadsContainer from './sidebar/uploadsContainer'
import WidgetsContainer from './sidebar/widgetsContainer'
2024-09-16 12:23:15 +05:30
import { DragProvider } from './components/draggable/draggableContext'
2024-09-24 11:50:50 +05:30
import PluginsContainer from './sidebar/pluginsContainer'
2024-09-30 19:13:26 +05:30
import { FileUploadProvider, useFileUploadContext } from './contexts/fileUploadContext'
import TemplatesContainer from './sidebar/templatesContainer'
2024-09-30 19:13:26 +05:30
import FrameWorks from './constants/frameworks'
import CustomTkWidgets from './frameworks/customtk/sidebarWidgets'
import CustomTkPluginWidgets from './frameworks/customtk/sidebarPlugins'
import generateCustomTkCode from './frameworks/customtk/engine/code'
import TkinterWidgets from './frameworks/tkinter/sidebarWidgets'
import TkinterPluginWidgets from './frameworks/tkinter/sidebarPlugins'
import generateTkinterCode from './frameworks/tkinter/engine/code'
2024-09-11 19:06:04 +05:30
2024-10-01 11:22:45 +05:30
import TkMainWindow from './frameworks/tkinter/widgets/mainWindow'
import CTkMainWindow from './frameworks/customtk/widgets/mainWindow'
2025-03-08 20:11:22 +05:30
import TreeviewContainer from './sidebar/treeviewContainer'
import { WidgetContextProvider } from './canvas/context/widgetContext'
2024-10-01 11:22:45 +05:30
2024-08-04 12:08:30 +05:30
function App() {
2024-08-04 22:47:43 +05:30
/**
* @type {Canvas | null>}
*/
const canvasRef = useRef()
2024-09-26 11:59:24 +05:30
const [projectName, setProjectName] = useState('untitled project')
const [UIFramework, setUIFramework] = useState(FrameWorks.TKINTER)
// const [uploadedAssets, setUploadedAssets] = useState([]) // a global storage for assets, since redux can't store files(serialize files)
2024-08-05 22:36:05 +05:30
2024-09-24 11:50:50 +05:30
const [sidebarWidgets, setSidebarWidgets] = useState(TkinterWidgets || [])
2024-09-30 19:13:26 +05:30
const [sidebarPlugins, setSidebarPlugins] = useState(TkinterPluginWidgets || [])
const {uploadedAssets} = useFileUploadContext()
// NOTE: the below reference is no longer required
2024-09-26 11:59:24 +05:30
const [canvasWidgets, setCanvasWidgets] = useState([]) // contains the reference to the widgets inside the canvas
2024-08-05 22:36:05 +05:30
2024-09-11 19:06:04 +05:30
const sidebarTabs = [
2024-08-04 22:47:43 +05:30
{
name: "Widgets",
icon: <LayoutFilled />,
content: <WidgetsContainer sidebarContent={sidebarWidgets} onWidgetsUpdate={(widgets) => setSidebarWidgets(widgets)}/>
2024-08-04 22:47:43 +05:30
},
{
2024-09-13 16:03:58 +05:30
name: "Plugins",
2024-08-04 22:47:43 +05:30
icon: <ProductFilled />,
2024-09-30 19:13:26 +05:30
content: <PluginsContainer sidebarContent={sidebarPlugins}/>
2024-08-04 22:47:43 +05:30
},
2025-03-08 20:11:22 +05:30
{
name: "Tree view",
icon: <AlignLeftOutlined />,
content: <TreeviewContainer />
},
2024-08-04 22:47:43 +05:30
{
name: "Uploads",
icon: <CloudUploadOutlined />,
content: <UploadsContainer />
},
{
name: "Templates",
icon: <DatabaseFilled />,
content: <TemplatesContainer />
2024-08-04 22:47:43 +05:30
}
]
2024-10-01 11:22:45 +05:30
useEffect(() => {
2025-03-14 16:42:27 +05:30
if (!canvasRef)
return
const canvasBoundingBox = canvasRef.current.getCanvasContainerBoundingRect()
const canvasCenterX = (canvasBoundingBox.width - canvasBoundingBox.left) / 2
const canvasCenterY = (canvasBoundingBox.height - canvasBoundingBox.top) / 2
// console.log("position: ", TkMainWindow.)
2024-10-01 11:22:45 +05:30
if (UIFramework === FrameWorks.TKINTER){
const widgetCenterX = (TkMainWindow.initialSize.width - canvasBoundingBox.left) / 2
const widgetCenterY = (TkMainWindow.initialSize.height - canvasBoundingBox.top) / 2
canvasRef?.current?.createWidget(TkMainWindow, {x: canvasCenterX - widgetCenterX, y: canvasCenterY - widgetCenterY}, ({id, widgetRef}) => {
2025-03-14 16:42:27 +05:30
// center the widget when adding to canvas
if (!widgetRef.current){
return
}
const widgetBoundingBox = widgetRef.current?.getBoundingRect()
const widgetCenterX = (widgetBoundingBox.width - widgetBoundingBox.left) / 2
const widgetCenterY = (widgetBoundingBox.height - widgetBoundingBox.top) / 2
// widgetRef.current?.setPos(canvasCenterX-widgetCenterX, canvasCenterY-widgetCenterY)
2025-03-14 16:42:27 +05:30
})
2024-10-01 11:22:45 +05:30
}else if (UIFramework === FrameWorks.CUSTOMTK){
2025-03-14 16:42:27 +05:30
canvasRef?.current?.createWidget(CTkMainWindow, ({id, widgetRef}) => {
// center the widget when adding to canvas
if (!widgetRef.current){
return
}
const widgetBoundingBox = widgetRef.current?.getBoundingRect()
const widgetCenterX = (widgetBoundingBox.width - widgetBoundingBox.left) / 2
const widgetCenterY = (widgetBoundingBox.height - widgetBoundingBox.top) / 2
widgetRef.current?.setPos(canvasCenterX-widgetCenterX, canvasCenterY-widgetCenterY)
})
2024-10-01 11:22:45 +05:30
}
2025-03-14 16:42:27 +05:30
}, [UIFramework, canvasRef])
2024-10-01 11:22:45 +05:30
2024-09-26 11:59:24 +05:30
// const handleDragStart = (event) => {
// console.log("Drag start: ", event)
// const draggedItem = sidebarWidgets.find((item) => item.name === event.active.id)
// setActiveSidebarWidget(draggedItem)
2024-09-26 11:59:24 +05:30
// const activeItemElement = widgetOverlayRef.current
2024-09-26 11:59:24 +05:30
// if (activeItemElement) {
// const rect = activeItemElement.getBoundingClientRect()
2024-09-26 11:59:24 +05:30
// // Store the initial position of the dragged element
// setInitialPosition({
// x: rect.left,
// y: rect.top,
// })
// }
// }
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
// const handleDragMove = (event) => {
2024-09-26 11:59:24 +05:30
// // console.log("drag move: ", event)
// }
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
// const handleDragEnd = (event) => {
// // add items to canvas from sidebar
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
// const {active, over, delta, activatorEvent} = event
2024-09-26 11:59:24 +05:30
// const widgetItem = active.data.current?.title
// const activeItemElement = widgetOverlayRef.current
2024-09-26 11:59:24 +05:30
// console.log("ended: ", activatorEvent.clientX, activatorEvent.clientY)
// // console.log("over: ", active, over, activeItemElement)
// if (over?.id !== "canvas-droppable" || !widgetItem) {
// setDropAnimation({ duration: 250, easing: "ease" })
// return
// }
// setDropAnimation(null)
2024-09-26 11:59:24 +05:30
// // Get widget dimensions (assuming you have a way to get these)
// const widgetWidth = activeItemElement.offsetWidth; // Adjust this based on how you get widget size
// const widgetHeight = activeItemElement.offsetHeight; // Adjust this based on how you get widget size
2024-09-26 11:59:24 +05:30
// const canvasContainerRect = canvasRef.current.getCanvasContainerBoundingRect()
// const canvasTranslate = canvasRef.current.getCanvasTranslation()
// const zoom = canvasRef.current.getZoom()
2024-09-26 11:59:24 +05:30
// let finalPosition = {
// x: (initialPosition.x + delta.x - canvasContainerRect.x - canvasTranslate.x) / zoom - (widgetWidth / 2),
// y: (initialPosition.y + delta.y - canvasContainerRect.y - canvasTranslate.y) / zoom - (widgetHeight / 2),
// }
2024-09-26 11:59:24 +05:30
// // find the center of the active widget then set the final position
2024-09-26 11:59:24 +05:30
// // finalPosition = {
// // finalPosition
// // }
2024-09-26 11:59:24 +05:30
// console.log("drop position: ", "delta: ", delta, "activator", finalPosition, canvasTranslate,)
2024-09-26 11:59:24 +05:30
// canvasRef.current.addWidget(Widget, ({id, widgetRef}) => {
// widgetRef.current.setPos(finalPosition.x, finalPosition.y)
// // widgetRef.current.setPos(10, 10)
// })
2024-09-26 11:59:24 +05:30
// setActiveSidebarWidget(null)
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
// }
2024-09-11 19:06:04 +05:30
const handleWidgetAddedToCanvas = (widgets) => {
setCanvasWidgets(widgets)
}
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
const handleCodeGen = () => {
if (UIFramework === FrameWorks.TKINTER){
generateTkinterCode(projectName, canvasRef.current.getWidgets() || [], canvasRef.current.widgetRefs || [], uploadedAssets)
2024-09-26 11:59:24 +05:30
}
2024-09-30 19:13:26 +05:30
else if (UIFramework === FrameWorks.CUSTOMTK){
generateCustomTkCode(projectName, canvasRef.current.getWidgets() || [], canvasRef.current.widgetRefs || [], uploadedAssets)
}
2024-09-26 11:59:24 +05:30
}
const handleFrameworkChange = (framework) => {
if (framework === UIFramework) return
2024-09-30 19:13:26 +05:30
// canvasRef?.current?.closeToolBar()
canvasRef?.current?.clearSelections()
2024-09-26 11:59:24 +05:30
canvasRef?.current?.clearCanvas()
setUIFramework(framework)
2024-09-30 19:13:26 +05:30
if (framework === FrameWorks.TKINTER){
setSidebarPlugins(TkinterPluginWidgets)
setSidebarWidgets(TkinterWidgets)
2024-10-01 11:22:45 +05:30
2024-09-30 19:13:26 +05:30
}else if (framework === FrameWorks.CUSTOMTK){
setSidebarPlugins(CustomTkPluginWidgets)
setSidebarWidgets(CustomTkWidgets)
}
2024-09-26 11:59:24 +05:30
}
2024-08-04 12:08:30 +05:30
return (
2024-09-08 21:58:53 +05:30
<div className="tw-w-full tw-h-[100vh] tw-flex tw-flex-col tw-bg-primaryBg">
2024-09-26 11:59:24 +05:30
<Header className="tw-h-[6vh]" onExportClick={handleCodeGen}
projectName={projectName} onProjectNameChange={setProjectName}
framework={UIFramework} onFrameworkChange={handleFrameworkChange}/>
2024-09-11 19:06:04 +05:30
2024-09-26 11:59:24 +05:30
{/* <Modal title={"FrameWork Change"} open={isModalOpen} onClose={handleCancel}
okText={"Yes"}
onOk={handleOk} okType={okButtonType} onCancel={handleCancel}>
<p>Are you sure you want to change the framework? This will clear the canvas.</p>
</Modal> */}
2025-03-08 20:11:22 +05:30
<WidgetContextProvider>
<DragProvider>
<div className="tw-w-full tw-h-[94vh] tw-flex">
<Sidebar tabs={sidebarTabs}/>
{/* <ActiveWidgetProvider> */}
<Canvas ref={canvasRef} widgets={canvasWidgets}
2025-03-14 16:42:27 +05:30
/>
2025-03-08 20:11:22 +05:30
{/* </ActiveWidgetProvider> */}
</div>
{/* dragOverlay (dnd-kit) helps move items from one container to another */}
</DragProvider>
</WidgetContextProvider>
2024-08-04 12:08:30 +05:30
</div>
2024-09-11 19:06:04 +05:30
)
2024-08-04 12:08:30 +05:30
}
export default App;