diff --git a/README.md b/README.md index 63539ee..3f28b91 100644 --- a/README.md +++ b/README.md @@ -37,20 +37,23 @@ Build Python GUI's with the ease of Canva ## Features * Framework agnostic - Can outputs code in multiple frameworks. * Easy to use. +* Pre-built UI components * Plugins to extend 3rd party UI libraries * Generates Code. ## Roadmap Here are some of the upcoming features. * Treeview on the sidebar +* Support for Event Handlers * Kivy Framework support * Pyqt/PySide Support * **Downloadable Electron app** and more. -To learn more/ see upcoming features visit [roadmap](./roadmap.md) +To learn more/ see upcoming features visit [roadmap](./roadmap.md) + +To stay in loop, subscribe to the free [newsletter](https://paulfreeman.substack.com/subscribe?utm_source=Github-Pybuilder) - -## License +## License - Fund the development To support open-source and development of this tool and upcoming free open-source tools and libraries, consider buying a one-time license. @@ -128,6 +131,13 @@ This is meant for business usecases, you can use the code even for commercial us * All code generated by the builder tools are free to use for commercial and non-commercial purposes. If you are using this for a startup or your business you'll need to get a commercial license. +## Some of my other open-source + +* [Awesome Landing pages](https://github.com/PaulleDemon/awesome-landing-pages) +* [Hover Preview](https://github.com/PaulleDemon/Hover-Preview) +* [Font Tester](https://github.com/PaulleDemon/font-tester-chrome) +* [Django SaaS Boilerplate](https://github.com/PaulleDemon/Django-SAAS-Boilerplate) + ## Author * Paul diff --git a/src/App.js b/src/App.js index 7338698..53395cc 100644 --- a/src/App.js +++ b/src/App.js @@ -1,8 +1,8 @@ import { useRef, useState } from 'react' import { LayoutFilled, ProductFilled, CloudUploadOutlined } from "@ant-design/icons" -import { DndContext, useSensors, useSensor, PointerSensor, closestCorners, DragOverlay, rectIntersection } from '@dnd-kit/core' -import { snapCenterToCursor } from '@dnd-kit/modifiers' +// import { DndContext, useSensors, useSensor, PointerSensor, closestCorners, DragOverlay, rectIntersection } from '@dnd-kit/core' +// import { snapCenterToCursor } from '@dnd-kit/modifiers' import Canvas from './canvas/canvas' import Header from './components/header' @@ -10,13 +10,12 @@ import Sidebar from './sidebar/sidebar' import UploadsContainer from './sidebar/uploadsContainer' import WidgetsContainer from './sidebar/widgetsContainer' -import Widget from './canvas/widgets/base' -import { DraggableWidgetCard } from './components/cards' import { DragProvider } from './components/draggable/draggableContext' -import { ActiveWidgetProvider } from './canvas/activeWidgetContext' import TkinterWidgets from './frameworks/tkinter/sidebarWidgets' import PluginsContainer from './sidebar/pluginsContainer' import TkinterPluginWidgets from './frameworks/tkinter/sidebarPlugins' +import FrameWorks from './constants/frameworks' +import generateTkinterCode from './frameworks/tkinter/engine/code' function App() { @@ -25,22 +24,16 @@ function App() { * @type {Canvas | null>} */ const canvasRef = useRef() - const widgetOverlayRef = useRef() - const [initialPosition, setInitialPosition] = useState({ x: 0, y: 0 }) + 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) - const [dropAnimation, setDropAnimation] = useState(null) - const [sidebarWidgets, setSidebarWidgets] = useState(TkinterWidgets || []) - const [canvasWidgets, setCanvasWidgets] = useState([]) // contains the reference to the widgets inside the canvas - const [activeSidebarWidget, setActiveSidebarWidget] = useState(null) // helps with the dnd overlay - - const sensors = useSensors( - useSensor(PointerSensor) - ) + const [canvasWidgets, setCanvasWidgets] = useState([]) // contains the reference to the widgets inside the canvas + const [canvasWidgetRefs, setCanvasWidgetRefs] = useState([]) const sidebarTabs = [ { @@ -61,87 +54,112 @@ function App() { } ] - const handleDragStart = (event) => { - console.log("Drag start: ", event) - const draggedItem = sidebarWidgets.find((item) => item.name === event.active.id) - setActiveSidebarWidget(draggedItem) + // const handleDragStart = (event) => { + // console.log("Drag start: ", event) + // const draggedItem = sidebarWidgets.find((item) => item.name === event.active.id) + // setActiveSidebarWidget(draggedItem) - const activeItemElement = widgetOverlayRef.current + // const activeItemElement = widgetOverlayRef.current - if (activeItemElement) { - const rect = activeItemElement.getBoundingClientRect() + // if (activeItemElement) { + // const rect = activeItemElement.getBoundingClientRect() - // Store the initial position of the dragged element - setInitialPosition({ - x: rect.left, - y: rect.top, - }) - } - } + // // Store the initial position of the dragged element + // setInitialPosition({ + // x: rect.left, + // y: rect.top, + // }) + // } + // } - const handleDragMove = (event) => { + // const handleDragMove = (event) => { - // console.log("drag move: ", event) - } + // // console.log("drag move: ", event) + // } - const handleDragEnd = (event) => { - // add items to canvas from sidebar + // const handleDragEnd = (event) => { + // // add items to canvas from sidebar - const {active, over, delta, activatorEvent} = event + // const {active, over, delta, activatorEvent} = event - const widgetItem = active.data.current?.title - const activeItemElement = widgetOverlayRef.current + // const widgetItem = active.data.current?.title + // const activeItemElement = widgetOverlayRef.current - 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) + // 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) - // 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 + // // 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 - const canvasContainerRect = canvasRef.current.getCanvasContainerBoundingRect() - const canvasTranslate = canvasRef.current.getCanvasTranslation() - const zoom = canvasRef.current.getZoom() + // const canvasContainerRect = canvasRef.current.getCanvasContainerBoundingRect() + // const canvasTranslate = canvasRef.current.getCanvasTranslation() + // const zoom = canvasRef.current.getZoom() - 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), - } + // 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), + // } - // find the center of the active widget then set the final position + // // find the center of the active widget then set the final position - // finalPosition = { - // finalPosition - // } + // // finalPosition = { + // // finalPosition + // // } - console.log("drop position: ", "delta: ", delta, "activator", finalPosition, canvasTranslate,) + // console.log("drop position: ", "delta: ", delta, "activator", finalPosition, canvasTranslate,) - canvasRef.current.addWidget(Widget, ({id, widgetRef}) => { - widgetRef.current.setPos(finalPosition.x, finalPosition.y) - // widgetRef.current.setPos(10, 10) - }) + // canvasRef.current.addWidget(Widget, ({id, widgetRef}) => { + // widgetRef.current.setPos(finalPosition.x, finalPosition.y) + // // widgetRef.current.setPos(10, 10) + // }) - setActiveSidebarWidget(null) + // setActiveSidebarWidget(null) - } + // } const handleWidgetAddedToCanvas = (widgets) => { console.log("canvas ref: ", canvasRef) setCanvasWidgets(widgets) } + const handleCodeGen = () => { + + if (UIFramework === FrameWorks.TKINTER){ + generateTkinterCode(projectName, canvasRef.current.getWidgets() || [], canvasRef.current.widgetRefs || []) + } + } + + const handleFrameworkChange = (framework) => { + + if (framework === UIFramework) return + + canvasRef?.current?.clearCanvas() + + setUIFramework(framework) + + } + return (
Are you sure you want to change the framework? This will clear the canvas.
+