fixed code generation and added asset generation
This commit is contained in:
2
notes.md
2
notes.md
@@ -6,4 +6,4 @@
|
||||
|
||||
|
||||
|
||||
## F\*CK Javascript, why the fu\*k, this.bind(this), class sucks in js, you can also use arrow functions, but you won't be able to override it in the subclass, because arrow functions, inherits from the surrounding context.
|
||||
### F\*CK Javascript, why the fu\*k, this.bind(this), classes sucks in js, you can also use arrow functions, but you won't be able to override it in the subclass, because arrow functions, inherits from the surrounding context.
|
||||
@@ -33,7 +33,9 @@ function App() {
|
||||
// const [uploadedAssets, setUploadedAssets] = useState([]) // a global storage for assets, since redux can't store files(serialize files)
|
||||
|
||||
const [sidebarWidgets, setSidebarWidgets] = useState(TkinterWidgets || [])
|
||||
|
||||
|
||||
const {uploadedAssets} = useFileUploadContext()
|
||||
|
||||
// NOTE: the below reference is no longer required
|
||||
const [canvasWidgets, setCanvasWidgets] = useState([]) // contains the reference to the widgets inside the canvas
|
||||
|
||||
@@ -140,7 +142,7 @@ function App() {
|
||||
const handleCodeGen = () => {
|
||||
|
||||
if (UIFramework === FrameWorks.TKINTER){
|
||||
generateTkinterCode(projectName, canvasRef.current.getWidgets() || [], canvasRef.current.widgetRefs || [])
|
||||
generateTkinterCode(projectName, canvasRef.current.getWidgets() || [], canvasRef.current.widgetRefs || [], uploadedAssets)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { createContext, Component, useContext, useState, createRef, useMemo } from 'react'
|
||||
|
||||
|
||||
// NOT IN USE
|
||||
|
||||
// NOTE: using this context provider causes many re-rendering when the canvas is panned the toolbar updates unnecessarily
|
||||
// use draggable widgetcontext
|
||||
|
||||
@@ -15,7 +15,7 @@ import { AudioOutlined, FileImageOutlined, FileTextOutlined, VideoCameraOutlined
|
||||
|
||||
|
||||
// FIXME: Maximum recursion error
|
||||
|
||||
// FIXME: Every time the parent attrs are changed a remount happens, which causes input cursor to go to the end
|
||||
/**
|
||||
*
|
||||
* @param {boolean} isOpen
|
||||
|
||||
@@ -7,9 +7,7 @@ import Cursor from "../constants/cursor"
|
||||
import { toSnakeCase } from "../utils/utils"
|
||||
import EditableDiv from "../../components/editableDiv"
|
||||
|
||||
import { ActiveWidgetContext } from "../activeWidgetContext"
|
||||
import { DragWidgetProvider } from "./draggableWidgetContext"
|
||||
import WidgetDraggable from "./widgetDragDrop"
|
||||
|
||||
import WidgetContainer from "../constants/containers"
|
||||
import { DragContext } from "../../components/draggable/draggableContext"
|
||||
import { isNumeric, removeKeyFromObject } from "../../utils/common"
|
||||
@@ -66,12 +64,6 @@ class Widget extends React.Component {
|
||||
// This indicates if the draggable can be dropped on this widget, set this to null to disable drops
|
||||
this.droppableTags = {}
|
||||
|
||||
// this.boundingRect = {
|
||||
// x: 0,
|
||||
// y: 0,
|
||||
// height: 100,
|
||||
// width: 100
|
||||
// }
|
||||
|
||||
this.state = {
|
||||
zIndex: 0,
|
||||
@@ -192,6 +184,9 @@ class Widget extends React.Component {
|
||||
this.load = this.load.bind(this)
|
||||
this.serialize = this.serialize.bind(this)
|
||||
this.serializeAttrsValues = this.serializeAttrsValues.bind(this)
|
||||
|
||||
this.hideDroppableIndicator = this.hideDroppableIndicator.bind(this)
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -206,7 +201,6 @@ class Widget extends React.Component {
|
||||
|
||||
this.load(this.props.initialData || {}) // load the initial data
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@@ -425,6 +419,17 @@ class Widget extends React.Component {
|
||||
return this.elementRef.current
|
||||
}
|
||||
|
||||
hideDroppableIndicator(){
|
||||
console.log("hide drop indicator")
|
||||
this.setState({
|
||||
showDroppableStyle: {
|
||||
allow: false,
|
||||
show: false
|
||||
}
|
||||
}, () => {
|
||||
console.log("hidden the drop indicator")
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -1073,135 +1078,137 @@ class Widget extends React.Component {
|
||||
|
||||
<DragContext.Consumer>
|
||||
{
|
||||
({ draggedElement, widgetClass, onDragStart, onDragEnd, overElement, setOverElement }) => (
|
||||
({ draggedElement, widgetClass, onDragStart, onDragEnd, overElement, setOverElement }) => {
|
||||
|
||||
<div data-widget-id={this.__id}
|
||||
ref={this.elementRef}
|
||||
className="tw-shadow-xl tw-w-fit tw-h-fit"
|
||||
style={outerStyle}
|
||||
data-draggable-type={this.getWidgetType()} // helps with droppable
|
||||
data-container={this.state.widgetContainer} // indicates how the canvas should handle dragging, one is sidebar other is canvas
|
||||
|
||||
return ( <div data-widget-id={this.__id}
|
||||
ref={this.elementRef}
|
||||
className="tw-shadow-xl tw-w-fit tw-h-fit"
|
||||
style={outerStyle}
|
||||
data-draggable-type={this.getWidgetType()} // helps with droppable
|
||||
data-container={this.state.widgetContainer} // indicates how the canvas should handle dragging, one is sidebar other is canvas
|
||||
|
||||
data-drag-start-within // this attribute indicates that the drag is occurring from within the project and not a outside file drop
|
||||
data-drag-start-within // this attribute indicates that the drag is occurring from within the project and not a outside file drop
|
||||
|
||||
draggable={this.state.dragEnabled}
|
||||
draggable={this.state.dragEnabled}
|
||||
|
||||
onDragOver={(e) => this.handleDragOver(e, draggedElement)}
|
||||
onDrop={(e) => this.handleDropEvent(e, draggedElement, widgetClass)}
|
||||
onDragOver={(e) => this.handleDragOver(e, draggedElement)}
|
||||
onDrop={(e) => {this.handleDropEvent(e, draggedElement, widgetClass); onDragEnd()}}
|
||||
|
||||
onDragEnter={(e) => this.handleDragEnter(e, draggedElement, setOverElement)}
|
||||
onDragLeave={(e) => this.handleDragLeave(e, draggedElement, overElement)}
|
||||
onDragEnter={(e) => this.handleDragEnter(e, draggedElement, setOverElement)}
|
||||
onDragLeave={(e) => this.handleDragLeave(e, draggedElement, overElement)}
|
||||
|
||||
onDragStart={(e) => this.handleDragStart(e, onDragStart)}
|
||||
onDragEnd={(e) => this.handleDragEnd(onDragEnd)}
|
||||
>
|
||||
{/* FIXME: Swappable when the parent layout is flex/grid and gap is more, this trick won't work, add bg color to check */}
|
||||
{/* FIXME: Swappable, when the parent layout is gap is 0, it doesn't work well */}
|
||||
<div className="tw-relative tw-w-full tw-h-full tw-top-0 tw-left-0"
|
||||
onDragStart={(e) => this.handleDragStart(e, onDragStart)}
|
||||
onDragEnd={(e) => this.handleDragEnd(onDragEnd)}
|
||||
>
|
||||
<div className={`tw-absolute tw-top-[-5px] tw-left-[-5px]
|
||||
tw-border-1 tw-opacity-0 tw-border-solid tw-border-black
|
||||
tw-w-full tw-h-full tw-bg-red-400
|
||||
tw-scale-[1.1] tw-opacity-1 tw-z-[-1] `}
|
||||
style={{
|
||||
width: "calc(100% + 10px)",
|
||||
height: "calc(100% + 10px)",
|
||||
}}
|
||||
ref={this.swappableAreaRef}
|
||||
// swapable area
|
||||
{/* FIXME: Swappable when the parent layout is flex/grid and gap is more, this trick won't work, add bg color to check */}
|
||||
{/* FIXME: Swappable, when the parent layout is gap is 0, it doesn't work well */}
|
||||
<div className="tw-relative tw-w-full tw-h-full tw-top-0 tw-left-0"
|
||||
>
|
||||
{/* helps with swappable: if the mouse is in this area while hovering/dropping, then swap */}
|
||||
</div>
|
||||
<div className="tw-relative tw-w-full tw-h-full" ref={this.innerAreaRef}>
|
||||
{this.renderContent()}
|
||||
</div>
|
||||
{
|
||||
// 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
|
||||
|
||||
`}
|
||||
<div className={`tw-absolute tw-top-[-5px] tw-left-[-5px]
|
||||
tw-border-1 tw-opacity-0 tw-border-solid tw-border-black
|
||||
tw-w-full tw-h-full tw-bg-red-400
|
||||
tw-scale-[1.1] tw-opacity-1 tw-z-[-1] `}
|
||||
style={{
|
||||
width: "calc(100% + 10px)",
|
||||
height: "calc(100% + 10px)",
|
||||
}}
|
||||
ref={this.swappableAreaRef}
|
||||
// swapable area
|
||||
>
|
||||
{/* helps with swappable: if the mouse is in this area while hovering/dropping, then swap */}
|
||||
</div>
|
||||
}
|
||||
{/* FIXME: the resize handles get clipped in parent container */}
|
||||
<div className={`tw-absolute tw-z-[-1] tw-bg-transparent tw-top-[-10px] tw-left-[-10px] tw-opacity-100
|
||||
tw-w-full tw-h-full
|
||||
${this.state.selected ? 'tw-border-2 tw-border-solid tw-border-blue-500' : 'tw-hidden'}`}
|
||||
style={{
|
||||
width: "calc(100% + 20px)",
|
||||
height: "calc(100% + 20px)",
|
||||
zIndex: -1,
|
||||
}}
|
||||
>
|
||||
<div className="tw-relative tw-w-full tw-h-full" ref={this.innerAreaRef}>
|
||||
{this.renderContent()}
|
||||
</div>
|
||||
{
|
||||
// show drop style on drag hover
|
||||
draggedElement && 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
|
||||
|
||||
<div className={`"tw-relative tw-w-full tw-h-full"`}> {/* ${this.state.isDragging ? "tw-pointer-events-none" : "tw-pointer-events-auto"} */}
|
||||
<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"
|
||||
/>
|
||||
`}
|
||||
style={{
|
||||
width: "calc(100% + 10px)",
|
||||
height: "calc(100% + 10px)",
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
}
|
||||
{/* FIXME: the resize handles get clipped in parent container */}
|
||||
<div className={`tw-absolute tw-z-[-1] tw-bg-transparent tw-top-[-10px] tw-left-[-10px] tw-opacity-100
|
||||
tw-w-full tw-h-full
|
||||
${this.state.selected ? 'tw-border-2 tw-border-solid tw-border-blue-500' : 'tw-hidden'}`}
|
||||
style={{
|
||||
width: "calc(100% + 20px)",
|
||||
height: "calc(100% + 20px)",
|
||||
zIndex: -1,
|
||||
}}
|
||||
>
|
||||
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("nw")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("ne")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("sw")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("se")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<div className={`"tw-relative tw-w-full tw-h-full"`}> {/* ${this.state.isDragging ? "tw-pointer-events-none" : "tw-pointer-events-auto"} */}
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("nw")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("ne")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("sw")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
<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 }}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.props.onWidgetResizing("se")
|
||||
this.setState({ dragEnabled: false })
|
||||
}}
|
||||
onMouseUp={() => this.setState({ dragEnabled: true })}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
</DragContext.Consumer>
|
||||
|
||||
@@ -109,7 +109,7 @@ export function DraggableAssetCard({file, onDelete}){
|
||||
|
||||
|
||||
return (
|
||||
<div draggable="false" className="tw-w-full tw-h-[240px] tw-p-1 tw-flex tw-flex-col tw-rounded-md tw-overflow-hidden
|
||||
<div draggable="false" className="tw-w-full tw-h-[220px] tw-flex-shrink-0 tw-p-1 tw-flex tw-flex-col tw-rounded-md tw-overflow-hidden
|
||||
tw-gap-2 tw-text-gray-600 tw-bg-[#ffffff44] tw-border-solid tw-border-[1px]
|
||||
tw-border-blue-500 tw-shadow-md ">
|
||||
<div className="tw-h-[200px] tw-pointer-events-none tw-w-full tw-flex tw-place-content-center tw-p-1 tw-text-3xl tw-overflow-hidden">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { memo, useState } from "react"
|
||||
import { memo, useEffect, useState } from "react"
|
||||
import { useDragContext } from "./draggableContext"
|
||||
|
||||
|
||||
@@ -15,11 +15,19 @@ const DroppableWrapper = memo(({onDrop, droppableTags={}, ...props}) => {
|
||||
allow: false
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (draggedElement === null){
|
||||
setShowDroppable({
|
||||
show: false,
|
||||
allow: false
|
||||
})
|
||||
}
|
||||
|
||||
}, [draggedElement])
|
||||
|
||||
const handleDragEnter = (e) => {
|
||||
|
||||
console.log("Drag enter")
|
||||
|
||||
if (!draggedElement || !draggedElement.getAttribute("data-drag-start-within")){
|
||||
// if the drag is starting from outside (eg: file drop) or if drag doesn't exist
|
||||
return
|
||||
@@ -71,6 +79,11 @@ const DroppableWrapper = memo(({onDrop, droppableTags={}, ...props}) => {
|
||||
|
||||
const handleDropEvent = (e) => {
|
||||
|
||||
setShowDroppable({
|
||||
allow: false,
|
||||
show: false
|
||||
})
|
||||
|
||||
if (!draggedElement || !draggedElement.getAttribute("data-drag-start-within")){
|
||||
// if the drag is starting from outside (eg: file drop) or if drag doesn't exist
|
||||
return
|
||||
@@ -78,10 +91,7 @@ const DroppableWrapper = memo(({onDrop, droppableTags={}, ...props}) => {
|
||||
|
||||
e.stopPropagation()
|
||||
|
||||
setShowDroppable({
|
||||
allow: false,
|
||||
show: false
|
||||
})
|
||||
|
||||
const dragElementType = draggedElement.getAttribute("data-draggable-type")
|
||||
|
||||
|
||||
|
||||
@@ -7,39 +7,46 @@ import TopLevel from "../widgets/toplevel"
|
||||
|
||||
// FIXME: if the toplevel comes first, before the MainWindow in widgetlist the root may become null
|
||||
// Recursive function to generate the code list, imports, requirements, and track mainVariable
|
||||
function generateTkinterCodeList(widgetList = [], widgetRefs = [], parentVariable = null, mainVariable = "") {
|
||||
let variableNames = [] // {widgetId: "", name: "", count: 1}
|
||||
function generateTkinterCodeList(widgetList = [], widgetRefs = [], parentVariable = null, mainVariable = "", usedVariableNames = new Set()) {
|
||||
let variableMapping = new Map() // Map widget to variable { widgetId: variableName }
|
||||
let imports = new Set([])
|
||||
let requirements = new Set([])
|
||||
|
||||
let code = []
|
||||
|
||||
for (let widget of widgetList) {
|
||||
// console.log("Key: ", widget)
|
||||
const widgetRef = widgetRefs[widget.id].current
|
||||
|
||||
let varName = widgetRef.getVariableName()
|
||||
|
||||
imports.add(widgetRef.getImports())
|
||||
requirements.add(widgetRef.getRequirements())
|
||||
// Add imports and requirements to sets
|
||||
widgetRef.getImports().forEach(importItem => imports.add(importItem));
|
||||
widgetRef.getRequirements().forEach(requirementItem => requirements.add(requirementItem));
|
||||
|
||||
// Set main variable if the widget is MainWindow
|
||||
if (widget.widgetType === MainWindow) {
|
||||
mainVariable = varName
|
||||
}
|
||||
|
||||
if (!variableNames.find((val) => val.variable === varName)) {
|
||||
variableNames.push({ widgetId: widgetRef.id, name: varName, count: 1 })
|
||||
} else {
|
||||
// Avoid duplicate names
|
||||
const existingVariable = variableNames.find((val) => val.variable === varName)
|
||||
const existingCount = existingVariable.count
|
||||
existingVariable.count += 1
|
||||
varName = `${existingVariable.name}${existingCount}`
|
||||
variableNames.push({ widgetId: widgetRef.id, name: varName, count: 1 })
|
||||
// Ensure unique variable names across recursion
|
||||
let originalVarName = varName
|
||||
let count = 1;
|
||||
|
||||
// Check for uniqueness and update varName
|
||||
while (usedVariableNames.has(varName)) {
|
||||
varName = `${originalVarName}${count}`
|
||||
count++
|
||||
}
|
||||
|
||||
const currentParentVariable = variableNames.find(val => val.widgetId === widget.id)?.name || parentVariable
|
||||
usedVariableNames.add(varName)
|
||||
variableMapping.set(widget.id, varName) // Store the variable name by widget ID
|
||||
|
||||
// Determine the current parent variable from variableNames or fallback to parentVariable
|
||||
let currentParentVariable = parentVariable || (variableMapping.get(widget.id) || null)
|
||||
|
||||
if (widget.widgetType === TopLevel){
|
||||
// for top level set it to the main variable
|
||||
// TODO: the toplevels parent should be determined other ways, suppose the top level has another toplevel
|
||||
currentParentVariable = mainVariable
|
||||
}
|
||||
|
||||
let widgetCode = widgetRef.generateCode(varName, currentParentVariable)
|
||||
|
||||
@@ -53,32 +60,32 @@ function generateTkinterCodeList(widgetList = [], widgetRefs = [], parentVariabl
|
||||
code.push(...widgetCode)
|
||||
code.push("\n\n")
|
||||
|
||||
// Recursively handle child widgets, which are full widget objects
|
||||
// Recursively handle child widgets
|
||||
if (widget.children && widget.children.length > 0) {
|
||||
const childResult = generateTkinterCodeList(widget.children, widgetRefs, varName, mainVariable)
|
||||
// Pass down the unique names for children to prevent duplication
|
||||
const childResult = generateTkinterCodeList(widget.children, widgetRefs, varName, mainVariable, usedVariableNames)
|
||||
|
||||
// Merge child imports, requirements, and code
|
||||
imports = new Set([...imports, ...childResult.imports])
|
||||
requirements = new Set([...requirements, ...childResult.requirements])
|
||||
code.push(...childResult.code)
|
||||
|
||||
// Track the main variable returned by the child
|
||||
mainVariable = childResult.mainVariable || mainVariable
|
||||
mainVariable = childResult.mainVariable || mainVariable // the main variable is the main window variable
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
imports: Array.from(imports), // Convert Set to Array
|
||||
imports: Array.from(imports),
|
||||
code: code,
|
||||
requirements: Array.from(requirements), // Convert Set to Array
|
||||
requirements: Array.from(requirements),
|
||||
mainVariable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[]){
|
||||
async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[], assetFiles){
|
||||
|
||||
console.log("widgetList and refs", projectName, widgetList, widgetRefs)
|
||||
console.log("widgetList and refs", projectName, widgetList, widgetRefs, assetFiles)
|
||||
|
||||
let mainWindowCount = 0
|
||||
|
||||
@@ -102,38 +109,37 @@ async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[]){
|
||||
return
|
||||
}
|
||||
|
||||
// let code = [`# This code is generated by PyUIbuilder: https://github.com/paulledemon \n`]
|
||||
// code.push("\n", "import tkinter as tk", "\n\n")
|
||||
|
||||
// widget - {id, widgetType: widgetComponentType, children: [], parent: "", initialData: {}}
|
||||
|
||||
const generatedObject = generateTkinterCodeList(filteredWidgetList, widgetRefs, "", "")
|
||||
|
||||
const {code: codeLines, imports, requirements, mainVariable} = generatedObject
|
||||
|
||||
// TODO: avoid adding \n inside the list instead rewrite using code.join("\n")
|
||||
const code = [
|
||||
"# This code is generated by PyUIbuilder: https://github.com/paulledemon",
|
||||
"\n\n",
|
||||
...imports,
|
||||
...imports.flatMap((item, index) => index < imports.length - 1 ? [item, "\n"] : [item]), //add \n to every line
|
||||
"\n\n",
|
||||
...codeLines,
|
||||
"\n",
|
||||
`${mainVariable}.mainloop()`,
|
||||
]
|
||||
|
||||
// TODO: create requirements.txt file
|
||||
console.log("Code: ", code.join(""))
|
||||
console.log("Code: ", code.join(""), "\n", requirements.join("\n"))
|
||||
|
||||
message.info("starting zipping files, download will start in a few seconds")
|
||||
|
||||
const createFileList = [
|
||||
{
|
||||
fileData: code.join(""),
|
||||
fileData: code.join("\n"),
|
||||
fileName: "main.py",
|
||||
folder: ""
|
||||
}
|
||||
]
|
||||
|
||||
// TODO: Zip asset files
|
||||
|
||||
if (requirements.length > 0){
|
||||
createFileList.push({
|
||||
fileData: requirements.join("\n"),
|
||||
@@ -142,6 +148,36 @@ async function generateTkinterCode(projectName, widgetList=[], widgetRefs=[]){
|
||||
})
|
||||
}
|
||||
|
||||
for (let asset of assetFiles){
|
||||
|
||||
if (asset.fileType === "image"){
|
||||
createFileList.push({
|
||||
fileData: asset.originFileObj,
|
||||
fileName: asset.name,
|
||||
folder: "assets/images"
|
||||
})
|
||||
}else if (asset.fileType === "video"){
|
||||
createFileList.push({
|
||||
fileData: asset.originFileObj,
|
||||
fileName: asset.name,
|
||||
folder: "assets/videos"
|
||||
})
|
||||
}else if (asset.fileType === "audio"){
|
||||
createFileList.push({
|
||||
fileData: asset.originFileObj,
|
||||
fileName: asset.name,
|
||||
folder: "assets/audio"
|
||||
})
|
||||
}else{
|
||||
createFileList.push({
|
||||
fileData: asset.originFileObj,
|
||||
fileName: asset.name,
|
||||
folder: "assets/media"
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// createFilesAndDownload(createFileList, projectName).then(() => {
|
||||
// message.success("Download complete")
|
||||
// }).catch(() => {
|
||||
|
||||
@@ -255,8 +255,6 @@ export class TkinterWidgetBase extends TkinterBase{
|
||||
|
||||
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
|
||||
|
||||
console.log("new attrs: ", newAttrs)
|
||||
|
||||
this.state = {
|
||||
...this.state,
|
||||
attrs: {
|
||||
|
||||
@@ -17,6 +17,7 @@ class MainWindow extends TkinterBase{
|
||||
this.state = {
|
||||
...this.state,
|
||||
size: { width: 700, height: 400 },
|
||||
widgetName: "main",
|
||||
attrs: {
|
||||
...this.state.attrs,
|
||||
widgetName: "main",
|
||||
|
||||
@@ -92,7 +92,7 @@ function UploadsContainer() {
|
||||
|
||||
<SearchComponent onSearch={onSearch} searchValue={searchValue}
|
||||
onClear={() => setSearchValue("")} />
|
||||
<div className="tw-flex tw-relative tw-flex-col tw-gap-2 tw-h-full tw-p-1 tw-pb-4">
|
||||
<div className="tw-flex tw-relative tw-flex-col tw-place-items-center tw-gap-2 tw-h-full tw-p-1 tw-pb-4">
|
||||
<Dragger className={`${dragEnter && "!tw-h-[80vh] !tw-opacity-100 !tw-bg-[#fafafa] tw-absolute tw-top-0 tw-z-10"} tw-w-full !tw-min-w-[250px]`}
|
||||
{...props}
|
||||
ref={fileUploadRef}
|
||||
|
||||
Reference in New Issue
Block a user