From 65d7aec1a27eb4bf0d730dca69b5a847aa64f26c Mon Sep 17 00:00:00 2001 From: paul Date: Sun, 22 Sep 2024 19:23:06 +0530 Subject: [PATCH] added MainWindow widget and updated readme --- README.md | 94 ++++++++++++++++++- assets/share/1.png | Bin 0 -> 8352 bytes assets/share/2.png | Bin 0 -> 14355 bytes assets/share/3.png | Bin 0 -> 14183 bytes assets/share/4.png | Bin 0 -> 12730 bytes notes.md | 3 +- roadmap.md | 2 + src/canvas/canvas.js | 5 +- src/canvas/widgets/base.js | 41 ++++---- src/canvas/widgets/widgetDragDrop.js | 15 ++- src/components/draggable/droppable.js | 32 +++++-- src/frameworks/tkinter/sidebarWidgets.js | 3 +- src/frameworks/tkinter/widgets/mainWindow.js | 46 +++++++++ src/sidebar/utils/share.js | 2 +- 14 files changed, 210 insertions(+), 33 deletions(-) create mode 100644 assets/share/1.png create mode 100644 assets/share/2.png create mode 100644 assets/share/3.png create mode 100644 assets/share/4.png create mode 100644 src/frameworks/tkinter/widgets/mainWindow.js diff --git a/README.md b/README.md index 340fe9b..cba3ea0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,21 @@ # PyUIBuilder - The only Python GUI builder you'll ever need +

+ + + + + + + + + + + + +

- - +Build Python GUI's with the ease of Canva @@ -10,9 +23,82 @@ * Framework agnostic - Can outputs code in multiple frameworks. * Easy to use. * Plugins to extend 3rd party UI libraries -* Generate Code. +* Generates Code. ## Roadmap +Here are some of the upcoming features. +* Treeview on the sidebar +* Kivy Framework support +* Pyqt/PySide Support +* **Downloadable Electron app** and more. + +To learn more/ see upcoming features visit [roadmap](./roadmap.md) -### All code generated by the builder tools are under MIT license and can be used commercially \ No newline at end of file +## License + +To support open-source and development of this tool, consider buying a one-time license. + +License will give you access to upcoming features, early access and more. + +The discount's will be available for limited time only on pre-orders. + +| Type | Free | Premium - Hobbyist / Per user | Premium - Commercial / Per user | +|-------------------------------------------------------------------|-------------------|----------------------------------------------------------|------------------------------------------------------------| +| **Support open-source development** | 👍️ | 😎 | 🚀 | +| **Priority support** - (priorities your feature requests, issues) | community support | ✅ | ✅ | +| **Lifetime license** (one-time purchase) | 👍️ | ✅ | ✅ | +| **Early access** to upcoming features | ❌ | ✅ | ✅ | +| **Downloadable Electron App** (upcoming) | ❌ | ✅ | ✅ | +| **Run Preview live**(upcoming) | ❌ | ✅ | ✅ | +| **Save and Load UI files** (upcoming) | ❌ | ✅ | ✅ | +| **Load 3rd party plugins locally** | ❌ | ✅ | ✅ | +| **Dark theme** (upcoming) | ❌ | ✅ | ✅ | +| **Commercial Use** | ✅ | ❌ | ✅ | +| **Support for PyQt/PySide frameworks** (upcoming) | ❌ | ❌ | ✅ | +| **More upcoming features and support** | ❓️ | ✅ | ✅ | +| **Price** | - | ~~$129~~ $29 (save 77.52% for limited time on pre-order) | ~~180~~ $49 (Save 72.78% for a limited time on pre-orders) | +| Pre-order now! | | [Get license]() | [Get license]() | + + +## FAQ + + +1. **Why do I need a GUI builder?** + + **A.** GUI builders assist you quickly create GUI without learning too much about GUI frameworks. It can also help you quickly prototype and see things visually. + +2. **Do I need to purchase a license to use this?** + + **A.** Webbased editor will remain free to use. To support open-source development, If you want a downloadable exe for local development and additional features, you'll need to purchase license based on your needs (hobbiest / commercial) + +3. **How does this compare to other UI builders?** + + **A.** + * Most GUI builders out there are framework specific, this UI Builder tool is framework independent. + + * This outputs code in Python, not in XML or other formats which can be hard to debug. So its easier to modify even after downloading the code. + + * Support for 3rd party UI libraries. Many GUI builders don't come with support for 3rd party libraries. + +## License Information + +To support development of this project, license differ depending on the usecase. + +#### Webbased Editor +* All code generated by the builder tools are licensed under MIT and can be used commercially + +#### Electron App - Hobbyist License +This is meant for students and hobbiest's +* All code generated by the builder tools are free to use for non-commercial purposes. If you are using + this for a startup or your business you'll need to get a business license. + +#### Electron App - Commercial License +This is meant for business usecases, you can use the code even for commercial use. +* 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. + + + +## Author +* Paul +* Github: PaulleDemon \ No newline at end of file diff --git a/assets/share/1.png b/assets/share/1.png new file mode 100644 index 0000000000000000000000000000000000000000..124c6a3193fa8c2cbf7925cc7f80c59e9a1115dc GIT binary patch literal 8352 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 literal 0 HcmV?d00001 diff --git a/assets/share/2.png b/assets/share/2.png new file mode 100644 index 0000000000000000000000000000000000000000..1d13164df8da32ae1ca1d5dbc04f97a4ba8483f6 GIT binary patch literal 14355 zcmd73Ra~6Swl|2o1$PS;w2?q?w_w5DY20ZXf-qUjUJ@0F5D5YT0##Z{ObG%4k`eqr5djMPeauZ61pYy^ zm(p~CfI#d0`+-bgKqG>HfHAdD(Ew@4$?_Q6*)SWL*ckzt-E8c^)DRGSf^PPP##TTO zxe?IJ!j_-*ytRXt+`@#PR{gUaK+awiXl^0p;RsarkXJGGurlU0p%oNB;&bBxGq3@I z49VSWtZkim-1uq#;mZU5|F@cj7EI)5V#=c=Ch>0)aEYJR90aoGVPSD~b!B#CXSQ=R zV`1gy=4Jt~v9Pf*fhm}r+-*UIZcMgLAHf`u$p7IX26QrZw6F(R*x8c*+KiqAdm<|7_asJzd87wr5p@|aLBlw8+W%{zcCtY~u8{_^&~f zfe!x^{#CNJ_-7=0Lq{i|in~3KpH>OzWasQ?4E%?~-%kH#BI*b<1OZJ1*Z^!COaN{s zHa0$%|E1~g82{Bl+zljcB4EsJ%w+^HVPj%5;^t!F;4(2{GBh^iU}7@?8gUtO15CL& z+5f}nUtRtu8wn#Ym(OgU**HIQvvROv~El$KvP3!YY?q~in_SC3b}$jxdu5C zIat>Ji%kD!!^iU9M)?0Ak^O)3>%X4&&+_`~bKnNBIPCux2VCM2b_SW-ISPCOPn7R( z^Z!`^_Va(H`Tt6z;Dz`fmHveKKJ4Y2eJ8J<^Lt7U^K9>Kr`u}z+ z|C$|mDT5a^%YT+WxbUCg0kj223`cNi$Tjoif`A~0kQNhGaZ5kdh4)ewpHn!X$~jze zoppA#X+3sXbsi}?t~_gLom1745()W+b13c+M=7P)6kZnH1_S6_kd=*KO;)}fR?vz$KXBE%=0(R zL-x5N9P`brBi5xY>2`90_jsfW^+AGIRD0gZrU|hy7pwf4w>pUS{JWwtf!KzQjv?N` zX&=5r@_X)1qRsZw*v3gL@*SG~#7{pe%-&j3u&|~C~f+<9=TMc#d0uy@P`3BoR zyPXG+@Q4SAZf*M~@cJ+bVUoQQa(%;FwiABP&e6U(>uzmZVP!2v-)#6N3vAyMU>v|4 z`dnDnq{pA7fbnU{h!Q17_R`37O00>3wavKqtbsz08Z2TK%* z$NbLYGcBnZRmq2H95_$MUXVMY=FcS}Q>*4-q`PHog#`y6a;SvNi{^1O#Fc+@!B4d? z2T6*A>4Gcvtv|#AJ|$}{-ixs&w$>sENgnukTVxm@Z@g*rlD$8a5WRN&FXZ}GT^@CS6uW$TZ-=I2IA84v3_x6A?SP;scX_6}< z!%#A{aL?|ia%QFu6O9zyLD6N1B{*7ZqB6(XU`a$aoT8(`yFFtqg#ul`j4myZ$D}W& z-x--rO;N#dl>u6fH2_A@szyhe(*T((t=krzJzM<94T~W7r^rCbtaDtEcvtOcuk&IA zvwx=NjO?uPI(pB!6mV~e?E1_s)dRAOXl5MK# zagTJ4Esd>!jpOmFiv_WHb)_lO+ylhm`{CG7NngDe?CzbNRd9b%N1tF&M# z1zEBTyc`;@wpNr}=%1kTkBGZVvDpHSGb+oEr8IL6w93r4&5le(TgcUu{xVb?T9(a)$AhMKCL zA6YtIT&QZG#E?9(gEnL>UhVXvL?a(DPY03i(CNy;Rce}N1wj6@q2$9z$w_n!$!{ti z)IZ`!FrU))PDc!XF2cVf^5iq{;|{~cx&j))se`MqKH+3Z>VLt|ZpfnKC@b}|G(xj= z@iup0OtY*@5yINlwI1ZrM?cLLHB0ss_7^h@Pmqey!fgt z`Q>Vrco&gfx@Ewjd>B#DLN@c+DpB34?8i0vqH`PLp7p*|(@D1P9JENU>3}5vxr=V? z64>1c>#u?63lW04#gjc#(|Y%EIRWfQ_!NfbzFIfiEAk5;c;))63G-XL%NbVJ_+b!v z5z>3l(u$IMjU3CKqw4PvY9FRyzJn@1Mz(HJbm)J0mvih>!0Ww$5w)>-oPS)nPadjM z7;m~C&VEHaR21`fF)Qx3Ad~;r@ZB{s3vS?dR*IaeCU%Aby~zjkf*iDD6Zaz6z@d} zhA)$)LJ!}WUwY0cq!xrXsO}hN#g|P|^iVxUq-Hh@(l}XfSY^{LPK!XK-GPs)FXHg~ zz{eT-Bt2Y8hV68xssJs<4jtloN4$_b#N}6DJzJ@hVd)l(F(|?g4e} zR>eYJ-Ox|2Bd+@@%FJk#*%gMtbXB5_MVmr-X+vqWvninbUCETi4SyDX*OCva;lgn? zr7b8(G(jtlN?)VoAp4`sY@%T(64UiyK zs5Hop(_aIagvvdCk#8o-P-d3qJA0MI@saunlhXBMWCuAOz!^CL(URh8igwCLwGhm> zyD7act#*@sAXCqT7BVAE1aX(_Ge{nxcbZ4QT(jCep=a9ei?%OV9^J;M5kpeA^~x%* zjLV@>jAxnl{SV&7pI|C$RqG*Y{XNLp`cQAYxXH9|n4HGZA5AuU^*^-D#Ik#qW@8=Z zp^6BT>ytYm1+5}+R|MFh3TdL}N%N!)b%Nv`rz|eiWwuhyS&Rer#GYA4bA}U{lDSO!XvblWcujG19wVs?{lL}35fCbP#@i{cJvitF0nlSz=+AYd>p2!l8Ux;m zxJaFu$1)WMz4kXBe%c~_8k=r1t;|pkwVb-TNw`iQZDZts#6Oz&%FJbPrQ-&`8z9$N z$`D=EwSGNZWGbm-d}RJep<+Dhnd0C+Tac8-JYTP(>j@D?#cgP*K? z)nL&A`jGR`M-gB9HHB-jkSsN90jS-@FiszTZYY}?C0Wk%Z1$A<>K^8~n!z|AtYkn= z-%j7vL7q07coh#&Q&q&yGZlT`njRQ|Yt^TR=cQ}Nk`+10BS}w!o$lQD;#OPHG+hFs z>i(!gAXfE2yE$HXi-Bt*8{Ibk1a}KfZ+odxu zl@bN2a-Ni52?WAg4E`=$44LUaMzr4*n*pV=E9&U9S=H=MaP)#azS%v0yqkX~;GiJb zpX+?{)y4Ehu#euY`TVmj0xy-iBTS&+suo+715@xqYNjFD=!AsveI_lo1Smzwoq+b6 ziLHPl3$4uHG#aDmDkQ0I1X)>~o__Vokd5mNy8hNNVM9iiWuzOrSpx#}d$Tb^S(#;y zBg#_{IZ%n34xk>GFB8xbFY0N);`j}CHQnUmVIz_$)L0Y zVXir>id45-=;hd-=~ zIcJ}@Jgh-M#QJMG9RE)@z)Jv$6X47UJ)!_~3qf+7#ihJeGC!q>$=wj7_w`5}Kc@CAbR_UUu!&5v{gg^SNQV{!ln>=t+Bmbxu+}b8nl^ zB{fWyouY+oopVOomxv^rbTHSnh0xE3CsD=W{RKZ;c!Io7Da4khQlOGpux0v-3@1Vi z#B#QaZPK9Pw#GZE!)Eu#hd-e`j|Y+j+513E@%EJq^$l%}MCCI0T&P!rQ4jalZi@Ti zwUfxcVK*_6KTW;|nH;-gc!@`j-Xjw`pN;;+ zyw&pf&Bu%qB)l&q->l5Vn>7|g&dkRV#U_#s4_F$#ku4t3lWCviE-mR+i6`18jyB6g zGzOS{riA&50HOJ~hE2qrYDlwArGD`oyg;b|Is=AGJ}paXu!1a*-kv-p?F;_u%N zBzhCN8`{Ma0$94v$#gKbCCW@d9@qK#osAx{5Zwjrm`N(fbe1g0Z_bj0;pC#lcLFw1 z94Xt!dtNcyw=a!lQBv{!g>GKDxk+KF1mF$?Ni692Vnw%%)b;cAY|DNw1 zeBUpV+?(z?kJ+zxPd|JqR#q0#WL)&wIy*FVw>QV7~x$28!7vK-m%n@q4bLTuy z5N<~X#vk?!#4!l@T>H=(KaAge;GGFMlR{reP!xWBPL@7u=Gmh)k^SwYMs?;{J(A;M zfW}|XO7Q!=mC3oNB>5h3o@?3XwS{s`D*=&4p1Jf?v{CquSk8sQa%#Rp?T}qqiwNR* zuIod8)`_Ei3DU4|PE7=p{4;KUHkp!OCp0`nkwT!LX+Lax*-2mvu6Z+T3Xlx5TjK{CG@f%=jRoBf8bj zct~xcax_3(1WEp0a8d=J=l?|wJ6*kQK(1&8Q-Um2tg4~%tkZHmV?za#bIzZNlDL#$ zJ3KK-RJhO<95nhSGVN4-D}bP^aZ%&m8!k3fY*qU%bqI9WlL!C^vsIt7z7{Mc@|sFi zzj}VjJr7e1{3_GRRm?O1%?sb5`Wy^EFkSmDUh@-e&yJ8-Rsz17$qzBAO0E-5{gIn$ zO5K!lY+2vrxU$d3)!KDk&fy{I6$O56ty-!O>;K93_ zmyMBxG>N&9o*%9a8A@({e=N&2G2NK?B^g{;7K}@FWHT*hd$sTYkObLZ*n5jx`ptBEX2yrJ+_?7)o+foST`oc>*3<_YMdaS;lZ+PI~EU% z+)ZYIaHM~{`%*wM8aq}G4`SF=|9FwpgDf;_ER0wA>TtaJatMbR3q*jKQH23xTjWMd|-LFAeOFaS80CP6ick{khJ~{UT&>XE8pOC|AqM38pm_^^;WK(W@ z?x3a|>{Ji^8xzT@`xlGk9vw!4C-;f9s$R26xzScit(~arFs%3ObJdq39lp8E{!gJn zC;nFwm~RrU5J#p;s_Rh0+`(Mt&~tEZF2q<3JtL0125DPRC|A)WXD~M()o$o!pjte7 zyM;H|AM+SZMJdbFiN{^-^>8P1ANdoDC%2#=?JPGH#xhR@&oD8Miu35ysZ4AaKA~Xu z`bsO+7#7(l>E8QPaw2+{;@u>v274 zQIxa`j`kVDB(n!g?)KkhN$^rSzti1VzhA0SP`o8ORwh<>lmwZ^Bi6^*-p%OPVCEjy z)A|>~#m>ojLVt1Rs4+TJcQ?qDU3YTnx$FkDq-3~8jISmI7z55mOwr&NxzB-9NMt{5 zHv=6LNq>`RlCFz#eual$wzm^N_VIMkrUyYDHS$S4LZ?fhh4J1O8gnzBl@zX!(AQ#-IBeg(0sU`BzUVjJwmR9Rg}J7Jsz2ttHP-J$F(@?h7Hs_ZwPz0L z`I%E+)%%$CLxI!%uE;ja8=I?-tY!iBrrg^&<@s3(N#A&K4AeoDGD?zvH`RVXC7S;8R=7Ak>+Xi8SJt? zta*lG)503>Ltp1vrTuWr&WZ?1hvz96Zf zC>UBfPx`rK*;H&}Ngb;`?pu++MVEro#9%!5xlSm=M5;@0PLiLTji4?W*!G=nLRfva z8j1ZrQ+&UOB?W);r9tT`p$Qc;O&X-oi-2MW1iSsO-qnIKATM%`Be z)k*%Wv&+aQIiw)c*EfckWzlg%Kuy`#?m)yD?8}6x8lLvGJXz!QBu)h>y+n-q;iA|C zi>q3JyH_}m!pRK-OsWW5c1~3PplzHTr4mths9T)-`8+w;tNUL;R9diFCvyaw2lm~9 z394LHQR2Onaxu_dIGImFhC+^sKWQ_$X=F0V9>Sn!PT4=MapKH#G+Fx$a=%#54mQp> zNY-0M&e~>fBv{T8!AsTHf$Z|z273~3BNQc5tZp`em-O)b2Oudg~!;Cu(`q*m~>@13F%tLmL9B$OFTqMVFtB8{P{kgwoYW-%(x{ zi1jd!JsN)v&3JdX=MkK1o()Oo`QWiUda%1WJ~ry$-=0sN_~dh%&|r zwpHlC$2MRbfq7eE&Q?nM&E#P#GmP_y|7yNb@0$JS_sGhAZ`vbeGF}`$Q5Jj$-@cu9 zaeaNa50&>6MeDtjhll8EyVj{oKolw3gX^2oyi?Xjbkp$V7ky9b9C05mgNA3h{rGQU zg*!c6CQP0Mnm^%Rt2I1exR0gLFv%>IL;{LVR!RA1+CQ*25nEG}P6@FusT{1GaQBB= zalZB+THn#i*a+iRZBpz+yL4Veui5sDt>%X$d2Aa#pD2)`jP8^u(wGH*6j|_F-(j?2 z=8`IGol3;E2oF+NWRD*7jpD>o0PyAG-9O;e3);q>P&5kGLgktK)EFMvZiTv>t98LA z*gBi^Jh7@=n7q=Zl*$NA?vh?i)dW8f90YaJ({6dUr!y_$-!s7C%j_Yy441dKWMQ2Zv^9yoC z_rVZ`q2-VHQ1J?x_MM{JVb09%T>0>?f?GzuZtqWlJoNUfU3qftWGytC>E7Ib4+ngW z1TW1@pWfHf`K-;f zimw{(U&zqoTzf=?Mf{G@NYW9Pcg_XNzeFtaFOu4yle0%?p;Sainb{Z~kG#KD&YQ~( zBj(^8ax)x9;@lO+oO>S<#Gc?kzHLjV;{{8;o4fq^Kqzt;8X`i1({#4+0Z|ZCqk*19 zJ4bzoZ_@?g1%7-B5gk{|^ss!AZo1`lB%jzA3XOm5kL!sfOg#mRfZ?6Tmfy~cNtIBy zgvPLhKJs>sf9gs5Wa;czbCf@@U$}c!JpCX-scCmlO$}T^9dz5h*ZoE5mo-gIdP-_9 zw5?*BdBjF6IT{ExPZCa*GXZlL80F_C6=(*D)no^uP(3Rj3`Wf6Nl<8V&{1=Y@QjSI z1G1Kng#qv2FnTe6hKPxz({V9L13FB05EV%B5`g8~eu)&5T zBwZ8FQ4k3M;RI`j1cKE)TYpZ{7l7G6WX69HO8o{s=$>?iz(e*peF5H&OGy%$7c;cw zLCt^Q!D-k#xWR;N(a6u^)pC}Ss!Y}`5x5iOakMHOZ#Vjv?$jiw`f8W8wkBbI{PKCx zb@JlLgmUY_))o$WO1I02MAC6>f|J5Gej(0J&DrbHn zz0D=q0bFt`Y3Yz=ee5s%77}iO6T-`kOHi%6D?fv|Jd>Mxz%T=wPz?R*vvo~J7pKeC&H}eDY)FMW2nYcj*lUU!+({ZHP@(n;9q#P#!pyw%$jW(1sVKzv_G_IhtK=Uc^C`@Y_GK+E+d?3C0;JL_Ta z%I#+-)@*{(W=%cSB{)98$u-1S1w)U5fyR}rp9n#Jb4Sq>@wmU=+jt<+Hyk;`YC9F8 z8>vvx<^&rsv=LKxrJMCPJf*5DM%>-nV<+2rED;cM?79y#M#q?3=sdjRUcr%{G!y0c zO_ML<4V=ki^;=z=lZ^`NUp3^J$CwN_NSel~O-nt!(TL`Jt3*}}cB6WOdc-v>v7!mS zB{puhF%`3BZWfDKz5AZi^0>LXb4Mg~$iH+2yQ&sk;E2w6J=N=&E>)kPlry_F_s6oz z)?AKXy>(gZ>ZWjK4fHXs?3jmK+kkNmHT*nuq-@VFt!EebyHg`CW~Wj=!<1^NSL66H zAIVw*zTJDnbWCy3KX4ufQ4#9JAt1l=wihG2(Oh;!ChH6Uh&xs6r z?t5tKG{MuB%UDFNQgE&ElYUx816RA&sK*S4cCThzv!2IC?5p$RxN6>Px5+^>8GimP z0{uGh?ldzoD);s>AwB&H3@E%_8@DACE%L&C>U?P<77IG}VEN;&j-$b1RzH*Ooj_wsv&z8 z2ymDF?fP>z{)OYNUG_FX+HLWhJ-!c6&OGt@tC?yr-H+MZ@mmc?#7m9i=pnpOg0@FxdIKucHtN_$LQE9u48Shw~uw4!J6F?Xqq%VV_HLVMdm z8Rg`XLk_8&g1xppNQ6Y`5a5_Q>Mv|^OFw)Bb4O}OgCHRERL_xnkx3Nkv&Ij(P0=N zAqM-D9@CyQogDlLE<;_qen|ZQ1%S$DpBgEL!`z^?*sa1&dDgslkIM=b32SVkNo2}H zoBf4xK%72x4kpzJ2V%n1&dHJ-@zwI}uz8lMF7C0+tjtYq-LM|P<98jU#g#DB^)$Za7%$4ZXrmQAT@dQh*Cwmu zFnYdrgGq4$P$l&>_54Z9bGr{8Z>Vn7Mm&<9CO!~pfm#>85*1AmCt25!>9$W_-29*3WyH?&cz~EC^V*wo1;D?9S#8|mM!6t-S#=pFak>Q@`&YOU)bLSj5 z9c>?NzzCCYE4zxX{+o$y-OR9RLf7f+G2?5v!o*d&nQ=>9HWw4|o{~hj|5ZPQvNhw5 zl;SI;S~B zE}9@0#p((0&PzBoGc~WZ%lDGcdd$@yl*`g}>?jQNC8h>8b z3YETV#zEMey+>L@O~DTx4!sq2b#dZX)bO+NYowu%y6PQ{nhmB0j)?{3?cu(Pd;fX` zMvx5REr&R1H8ppJ3?VK?HEh-0oA(WN5BuukHjNbA`;fPLXN(1Eu+$a<{OLm6u35u% zG%&3rs<4JN6P()_4Z1|gx_s-I#7MuID}t}u$TEp`_xy3HXY>{kj;LCbW{`-D_TFpx z9hTeB-bx2?u>sEe%R7b!-u*iHMw+kKz9nc^*jC3s*7F(&-ZV(**g;SLbdip0_j*QV ze136Mrp%Q8maCYQknwzAU%2wt{xm z2=)qKhtsRHqy8>3UuH;O1S=3^?1!sS|8mt&6fZ!eN|35`0!F2mXM&ak^qCC4K68A7 z|K^-e&wp@%W}69vn)Rv7k|m6o8u}FFU6$Ms zJCg!P01!Uw3#RBg8-+g*3$Fk|!)pf@V1MqgQ9I~2p-JM-I|gbxi-l%F{|*9jJHh>h zYa*RJMh?#P7t_2y8v)iNUDZ>QQ*jxQh9AF=OtIw|tv|sp^$Eq9^NWc^+63%+FqVz zPz9Is1OXRqZ)pbZP0T_15xPx5mbm@`Q2~T3qroLyTiSR7ux!|u`kn2JGCaJp;r*7- z>h&_6uB~N+Sz+F_1NSE{w^wl~L57TqoHgoX=Xn}l1(J_CPO?T@-l(XM=RKF)^2f2< zhlg|)$F|IOm)jU9_@bH_W1SWWQywW1^~gA@ivZwgv@}A%Sy>h^fbeB9SL0h6nFhw| za)AT9(a3iW-r=5C)YIJcrf)KZPIT?LO-Qr9vJ?1w`NKkSuWL7Cal|yg5@VWJr3a}W z5o(8+~c9<#DH`$Zqw^x1gO<-K6GMFA$Aow$?blHjM^-bR9x$Agn+h|Zn5$-%{a<5(H zH#~d|4?*B3s(=B%37qL*JGrnWh6suy5@OZ;1Q9ZXbkvyg^sJ+jQ!Mo^%V#+0a8XeOg^yLxe3kNb zUx=*JXZ{HtW|VaM@=IH(tI5aK3hBa0Qp#b!(KOfe_F+lPItiEiqC2h$Y1Itf9*l&k zjQEooakC)X@#b`F!dHpuWmmeNq=$VT6XFY@VO&;^qo66aqD&=1xUoy>n;$HaFNK0o zF^1Q0y{8Z8_{fipKCKp-usPtAmohbIj4?~)z?wJKoKbqK$IZ`7F}_@d;FE=nov^Q} z>K9Y+LW48QjO!&X4aBl-u=k1h$`ykVvMdd1YG;;O81>Q=HvLAgx03jDQR^1HRI#3+ z{Q_hTrvV(j+q?Wpqn&WaH<*>*4(AwKDVsd|S0n&uxL@`V|HQkoATP-Ce_2Kh8C+E( zF@}79L?iRc8^u73)=`m3(vubdWO0lv!~ zBXFPM+x3}#_P`3ckrakNs#tKQ2}ZPaHbQ95Cp%}UcbF5 zm`c7{DYN}FKfKArKH0bznc!^-D#U9j>^_ErUk2qhCMOg;pImEaXc0tCf^nE{bt(;5 zg^*!Mh;l@Y9Q&QsCowB~h;qT%!8vW1XtF2~!_6lf@!H*+5PgYK>F#R8YA||nv;GiU zJChZ)EpuK3_NwG<@%^3)F9(M>P1Lz&(F8khU?>VFp6gpz+@4u--dWBapA2HX=&a&& z#IcqT??E1lj~Q(Ly+FmvhQGBw2r%E}u2149!#UG=Q-=Nd=mVldwIAjSNH{#f!?9{{ z5d)UHwVc#ikOR@nqL*AYxW~27ZyL6~$zAIqKWe<3SM7(XwizK>1gcw~1&=@5@xh)2 zXPZ(eqm1PSiMhkAwM|?`)R0itnut!$-YHkaDGanb3csI!#MV`8z_vmeW_lNwSFk*h z(pB3>ep3B3-xR9kBWX zu8oi4c{wjbx{+=viy*0bl|+bc$?RVD`**r}4d$HO`v8=llbRltHf88aB<&+iGM$(;8BI^JQqaZMfZSj!DVd`R}IGcl+-ZO z?>?_|1x^&sBkr1gJ-)08|DNo^TKvS34tpHQ5IA{=CeIa|#G_ftXdkxoqGGLNh>2!- z+SSDNo8U5}N9Q6UhAN*;QoiD<`x#nNrwjpbPl8wKST3sF^TO`th(F3s9v@w}-o*Sv zU)1|5g{g#8{*RXsiahU$W;`i|+N>WPz|JJo_30oML1wlAYneuWY!zX0nCbYJ#0I+w z@{Ftfetix3D99a)iRNQb_qUpUj4b^Q=AZ|+TrBRM;MbqHV@Wx>=%Nf}MjQ=wF}qhn z?CY@R>Qy|sh#C8w3Ky`pF6~`GcZG)qr=b}$3nyhw7p?))gT+7mMCNI9DhhH>rm+}B zTj{S5A|hZ_ep#B=$P`*wX&Z;>;?>IqQjK)bNRSkBz5F`(;R(L5ET9G_p${TlaClNbi1QhhP&e2`fkj_Swc1nD1al&B;dD%YKTLE6Tlq80+Mr{gA8IY%fZZZ_ys zmzHSB_`_ zgq#QoN3R>l5e9Z>(`Z4BXuN4t>r}d7-5K=uf_Pp|3FP3bj5kG&0Go*v z=XLB#z7xM$k2-_C&6ieF@!ZfsLF6Y={JPki$N|~1@Sz9V;s#Tyxm4-sCgeKFD}~F+juS<-LzmFCM@1XmV~-_KUlq8b z42DbWzcHIH<3jk*c!MO;f^qPd+=tZN0jn_pS2?2LVG)!TzHG>x3#Yr??Bj>h;aGCR z0Z6`^J1*Ur*(G((=|2;ZD2lfn4lgj8ZNa=*&gZiJ1MQNf>$}G^J)0Emx*=AvGlvP( zW}er+I9?@7LHANvWvLBHJiexgfB>fbp~L&v2S+sYOH$xbm2@6mbz#P=jewe>!$F=c z29+@QYH%lxRz+!$-J8PF=qng&un~mloNWcMgRmk`c&C82(3O)c+1!MAuQ%U0*yiHy z?p5bJeDxw!U~Oqdfqhk_p9abQH+;Y2|EJeX!rx(!UZEVOL?`P0zP2YVE-zLoV&MOO E0AYC5D*ylh literal 0 HcmV?d00001 diff --git a/assets/share/3.png b/assets/share/3.png new file mode 100644 index 0000000000000000000000000000000000000000..10adfb166fd0ed830335a5b511e8e8072b88e5e9 GIT binary patch literal 14183 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 Dmr(if literal 0 HcmV?d00001 diff --git a/notes.md b/notes.md index e0c1c09..a3e9c64 100644 --- a/notes.md +++ b/notes.md @@ -1 +1,2 @@ -### State management in react is a f*king mess \ No newline at end of file +### State management in react is a f*king mess +### Update to TypeScript \ No newline at end of file diff --git a/roadmap.md b/roadmap.md index 786ef74..538f58d 100644 --- a/roadmap.md +++ b/roadmap.md @@ -9,6 +9,7 @@ Any feature that has 👑 beside it, is meant only for [premium users](./readme. - [ ] UI fixes and enhancement - [ ] Tree view for elements on the canvas - [ ] Add text editor to support event handlers +- [ ] Support more widgets - [ ] Rewrite DND for better feedback - (swappy/react-dnd-kit/ GSAP draggable) - [ ] Duplicate widgets @@ -23,6 +24,7 @@ Any feature that has 👑 beside it, is meant only for [premium users](./readme. ### 2.0.0 - [ ] Support for more third party plugins - [ ] Support more templates +- [ ] Allow creating components - [ ] Support for Kivy - [ ] Sharable Templates - [ ] Dark theme 👑 diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 9accaab..17c9163 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -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 { {/* */} {/* */} diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js index 51761fa..3197363 100644 --- a/src/canvas/widgets/base.js +++ b/src/canvas/widgets/base.js @@ -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 ( -
+
{this.props.children}
) diff --git a/src/canvas/widgets/widgetDragDrop.js b/src/canvas/widgets/widgetDragDrop.js index 58557a5..07b4707 100644 --- a/src/canvas/widgets/widgetDragDrop.js +++ b/src/canvas/widgets/widgetDragDrop.js @@ -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 } diff --git a/src/components/draggable/droppable.js b/src/components/draggable/droppable.js index eb7c9bc..259af3d 100644 --- a/src/components/draggable/droppable.js +++ b/src/components/draggable/droppable.js @@ -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) } } diff --git a/src/frameworks/tkinter/sidebarWidgets.js b/src/frameworks/tkinter/sidebarWidgets.js index b60ac4a..c5a5b9b 100644 --- a/src/frameworks/tkinter/sidebarWidgets.js +++ b/src/frameworks/tkinter/sidebarWidgets.js @@ -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", diff --git a/src/frameworks/tkinter/widgets/mainWindow.js b/src/frameworks/tkinter/widgets/mainWindow.js new file mode 100644 index 0000000..726d8a3 --- /dev/null +++ b/src/frameworks/tkinter/widgets/mainWindow.js @@ -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 ( +
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.children} +
+
+ ) + } + +} + + +export default MainWindow \ No newline at end of file diff --git a/src/sidebar/utils/share.js b/src/sidebar/utils/share.js index 705a708..be38308 100644 --- a/src/sidebar/utils/share.js +++ b/src/sidebar/utils/share.js @@ -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" } }, [])