teavm
teavm copied to clipboard
Please port Swing to TeaVM
First of all TeaVM is such an amazing project and it should be noticed even more - porting Swing could do the trick! Swing on TeaVM (I am aware of SnapKit) is far simpler then you probably realize. It would also not blow up the overall code one has to download. This is not the full JCL - Swing is just a tiny part. A lot of work has already been done in form of the Cacio project: https://en.wikipedia.org/wiki/Abstract_Window_Toolkit#Implementation
I've put the caciocavallo repo online for you so you can explore more easily: https://github.com/suthcark/caciocavallo
Cacio is a super-tiny piece of software that's comprised of:
- A porting layer for AWT widgets. This implements the peer interfaces and uses Swing to provide AWT widgets. Very useful on platforms that don't provide any native widgets, or if you're simply too lazy and don't care about AWT ;-)
- A windowing layer that basically provides heavyweight windowing all in Java. This implements some interfaces of the above AWT porting layer, and can provide HW windowing, for example, on systems that only have a sort of graphics/framebuffer, but no native windowing.
The above are only support layers and don't do much themselves. There are however a number of actual ports that use the above 'core' Cacio stuff, plus tons of stuff from the desktop module (namely, SunGraphics2D, SurfaceData, fonts, etc):
- An SDL port
- A DirectFB port
- An implementation that only renders into BufferedImages and uses Robot to simulate events. This is extremely useful, and infact used for GUI testing:
- An implementation that renders into an HTML5 canvas using a webbrowser, i.e. the Swing application runs on a server, client accesses it through a browser. Browser renders graphics using JavaScript/HTML5 and sends back events to the server. This is called CacioWeb
Further reading about the architecture and different implementations:
Initial Proposal: http://mail.openjdk.java.net/pipermail/challenge-discuss/2008-March/000082.html http://rkennke.wordpress.com/2008/12/18/caciocavallo-architecture-overview/ http://rkennke.wordpress.com/2008/09/03/cacio-swing-awt-peers/ http://mail.openjdk.java.net/pipermail/caciocavallo-dev/2009-September/000184.html http://rkennke.wordpress.com/2011/07/28/jdk7-and-cacio-coolness/ http://www.webcitation.org/1312943154337056 http://rkennke.wordpress.com/2012/05/02/caciocavallo-1-1-released/ http://rkennke.wordpress.com/2012/12/12/quick-cacio-web-howto/
The OpenJDK project caciocavallo dissolved just this month but it will come back to Github soon: https://mail.openjdk.java.net/pipermail/caciocavallo-dev/2019-June/000573.html
Cacio is also available in Maven Central and some of its implementations are part of other projects on Github: https://mvnrepository.com/artifact/net.java.openjdk.cacio https://github.com/iaavo/provolone https://github.com/UISpec4J/UISpec4J
First of all, AWT and Swing port can be made as a separate project. Just follow package naming convention and use T
prefix (see classlib
module) and this should work. Second, personally I'm too busy to maintain such a project. Third, I just don't see any purpose on porting Swing. Can you tell me why you think it's really necessary? TeaVM is not focused on running existing Java, applications, it trades compatibility for efficiency. So running something like, say, IDEA is a non-goal and there are 1000 other things that aren't supported in TeaVM to run IDEA. Fourth, Cacio is licensed under GPL, which is incompatible with Apache License used by TeaVM.
I have to admit this intrigues me, as an old-time Swing developer. I was very interested in the cacio-web project as well. I think there are still Swing projects out there that would like to move to the web. This could be a nice way to get them started with TeaVM easily, if done as a separate project like @konsoletyper says.
@suthcark , what is the bare minimum required to implement the rendering to an HTML5 Canvas? I saw WebToolkit class in cacio-web that looked like a potential starting place.
@konsoletyper: I bet the original cacio authors would probably agree to offer it under another license. Also don't underestimate how well and by how many people the Swing API is loved and understood. It would be a huge boost for TeaVM
I don't think cacio-web is the way to go, since it is a client-server solution. We want Swing 100% running on the client. Still, it probably can't hurt to look at cacio-web at a later point ;)
The best way to approach this in my opinion is to look at cacio-core first and read the links I added above about Cacio's architecture. Then one should look at how the various implementations are done on top of cacio-core, starting with the simplest one: cacio-tta and then maybe ciacio-directfb. It's all here: https://github.com/suthcark/caciocavallo
Also the implementation part for running Swing on "for HTML5/JS/TeaVM" is basically already done with these two projects: https://github.com/reportmill/SnapKit https://github.com/reportmill/SnapTea
@reportmill (Jeff Martin) developed an impressive UI toolkit in pure Java that can be compiled to "HTML5/JS". All the low level stuff needed for the implementation of cacio-core is already there: surface to draw on, event handling, font handling and rendering, etc. I emailed with him yesterday and he may put a architecture overview together soon. He told me:
The primary set of abstraction/adapter hooks are in these two classes: snap.gfx.GFXEnv: Includes hooks to create Images/Fonts which are subclasses specific to platform snap.view.ViewEnv: Includes hooks to create Event (subclass specific to platform) and handles running on App thread A typical SnapKit app centers around the snap.View.ViewOwner class, which has methods to load UI, resetUI and respondToUI(). Most of my apps are just nested instances of ViewOwner subclasses.
Then I would carve out Swing from the OpenJDK repo. One should make sure it works perfectly together with cacio-core. Maybe one would need to extend cacio-core a bit if there are some native calls needed by Swing not covered by cacio-core - I am also an old-time Swing dev but I don't know it by heart so maybe this is necessary, maybe not, maybe one could remove these parts. Although I think it would be nice if one could leave Swing as untouched as possible. It could be a starting point to separate Swing from its marriage to the OpenJDK/JCL and with the help of cacio-core develop it as a pure Java library drawing all native parts from the JCL. Swing 2.0 could be possible once it is extracted.
Then it would be basically putting all the parts (cacio + SnapKit + SnapTea -> Swing) together.
One could even think about a Android and iOS port of Swing. Projects like https://github.com/libgdx/libgdx https://github.com/playn/playn
both implement their own UI toolkit in pure Java with all the native parts abstracted away and drawn from Android or iOS. It is compiled via https://github.com/MobiVM/robovm to run on iOS natively. Clipboard support and everything. Like SnapKit/SnapTea those projects basically also have the low-level details all sorted out for us. Drawing on a surface, event handling, fonts, and much more. It could all be used to implement cacio-core for those platforms. Swing would then work automatically on top of it. All of it could be 100% pure Java.
+1
@suthcark sounds like you know your stuff very well and put a lot of thought and research into this :)
@suthcark @ScraM-Team I am also an old time Swing fan! I could help out in case you go forward with this.
@dwaal thanks. Obviously I didn't want to start this in an echo chamber. This issue is quite good to get feedback and maybe decide if and how to get this done. I was thinking a long time about "freeing" Swing from the shackles of the JCL and making it a 100% pure Java library that can finally be improved. The other half of my thinking goes towards porting Swing to the browser, Android and iOS and making it easy to port it to any new platform in the future.
Also don't underestimate how well and by how many people the Swing API is loved and understood.
My experience is different: Swing is horrible, and many people around share this opinion. The only reason why it was popular in Java is it's only UI toolkit in Java. Do you know widely-used Java applications (except for IDEA and Netbeans) that use Swing? And BTW do you know any widely-used desktop Java applications?
Anyway, imagine I'm wrong and there are lots of Swing applications and their developers want to port them to the web. Ok, TeaVM might have supported Swing, but there are many things that aren't supported by TeaVM (and never will be), so it's never possible to port thing seamlessly. Moreover, seamless porting of existing Java applications was never a goal for TeaVM and never will be. This niche is covered by CheerpJ, which has its own drawbacks like giant JavaScript and huge loading times. TeaVM is more competitor for tools like GWT, JSweet or Kotlin/JS: you write new code which runs in TeaVM (and therefore runs on desktop JVM or Android the same way) or you put efforts and port all your existing code to be compatible with TeaVM. If you run Swing on TeaVM, it will lose its advantage over CheerpJ: speed and size, with no other advantages over CheerpJ (like compatibility).
Also, I want to repeat it once again: I barely have time to maintain TeaVM. I have no time to port Swing or other big libraries. If you really want some library to be ported, you must find someone else to do that. Of course, I can assist you by fixing bugs in TeaVM or trying to implement missing features or by explaining how to do this or that thing with TeaVM.
My experience is different: Swing is horrible, and many people around share this opinion.
Swing is actually quite nice but most books teach it wrong so you basically use a black box and everything is trail-and-error. Code changes, launch, frustration - until it works. It's kind of how 99% of people use Gradle. Their tutorial/doc is horrible. People use it wrong. Under the hood Gradle is very nice and if you know how to use it, it is very good. It could be amazing if they didn't force you to always use the script/launcher mechanism instead of writing everything programmatically in code (but that's a different story).
I know quite a few apps in Swing. Also very popular desktop apps. The reason it is not more popular on the desktop has historical reasons (I can elaborate if you like). Also Sun didn't put enough manpower into fine-tuning it and it really got only good with Java6+.
Anyway, even if Swing is dead on the desktop (which it isn't), but let's assume it is, porting Swing to the browser and Android and iOS turns Swing into something else. A universal UI toolkit where you can develop your code on the desktop (very quickly) and deploy to browser and mobile. Imagine how nice it would be if during development you could launch an Android app directly on the desktop like you instantly launch any other Java app. The way it is with browser and mobile you always have a slow compilation or build - package - deployment step.
Moreover, seamless porting of existing Java applications was never a goal for TeaVM and never will be. This niche is covered by CheerpJ.
Exactly. Swing doesn't need the full JDK/JCL. It could be slim and fast in the browser. Look at SnapKit. Swing is nothing else then SnapKit technically - just a little bigger. Actually if we had a Swing port in the browser, SnapKit/SnapTea could use it under the hood to target the browser (although its current implementation is probably cleaner).
Also, I want to repeat it once again: I barely have time to maintain TeaVM. I have no time to port Swing or other big libraries. If you really want some library to be ported, you must find someone else to do that.
Don't worry. No pressure. Let's just keep this issue open so we can discuss things.
Swing is actually quite nice but most books teach it wrong so you basically use a black box and everything is trail-and-error
First of all, I never read any books and prefer to learn things by documentation (javadoc in case of Swing) and experience, and I still think Swing is horrible. Another reason: a good library don't need some 'right' explanation to look good.
It's kind of how 99% of people use Gradle. Their tutorial/doc is horrible. People use it wrong
Right. As well as CMake, as well as Spring, as well as C++ used to be 15 years ago. Their problem: there are 1000 ways of doing a thing, one is right way, and 999 either deprecated or for some very special case. And documentation does not describe this, only states 'there are following 1000 ways of doing this thing: ...' But this still means that library is horrible, because API is not self-descriptive, because documentation is horrible and because community is not satisfied.
A universal UI toolkit where you can develop your code on the desktop (very quickly) and deploy to browser and mobile
Ok, I see you point and I share it. Personally I want something like that, but it should not necessarily be Swing. Swing is quite old, relies on old Java (back in times there weren't generics, lambdas and even enums) and too heavyweight for web. Consider designing some alternative, like SnapKit, Codename One, etc. In CoSpaces Edu we built our own UI toolkit (which is still horrible like Swing, but much-much more lightweight) which runs on many platforms, though it's proprietary. But this proves it's possible. I'd created something like that, because creating multiplatform toolkit is something promising today, when there are React Native, Xamarin, Flutter, and nothing similar for Java. I even thought about implementing and XML layer over Swing and Android UI and binding this XML to Flavour, but still have no time for that.
Another reason why I think Swing does not fit for this purpose is the need in natively-looking UI. I mean no just rendeing widgets that look native. I mean native UX, which is quite different on different platforms (and can never be the same on desktop/mobile/tablet/console devices). My thought was: allow to develop business logic on Java, describe UI declaratively using HTML/XML with binding language and requiring developers to maintain separate HTML/XML template for each platform. I know that's some kind of overhead and duplication, but it's still very small (99.9% of code will be common Java) and gives native-looking UI and UX.
Right. As well as CMake, as well as Spring, as well as C++ used to be 15 years ago. Their problem: there are 1000 ways of doing a thing, one is right way, and 999 either deprecated or for some very special case. And documentation does not describe this, only states 'there are following 1000 ways of doing this thing: ...' But this still means that library is horrible, because API is not self-descriptive, because documentation is horrible and because community is not satisfied.
Can you point me to a couple of specific examples you don't like with Swing? UI toolkits (especially those who do much more then buttons) are by definition difficult to use. This isn't comparable to CMake or Gradle where there is no reason that it is difficult to use.
Swing is quite old, relies on old Java (back in times there weren't generics, lambdas and even enums) and too heavyweight for web.
It is old. You could also say mature. Tested by millions. Also it is very complete and has a lot of open source 3rd party support. Once it is freed from the JCL and 100% pure Java one can refactor the hell out of it as long as the public API stays intact. Heck you could even extend that API and integrate new bugfixes from the JCL.
I don't want to reinvent the wheel again - not because it is hard but because nobody needs another UI toolkit (this is not the Javascript world). 100% of Swing is there. We just need to implement the low-level code for each platform. Cacio, SnapKit/SnapTea, libGDX, playN, etc. can help with implementing this. What makes Swing special is that everything you see is drawn by Swing. Not some thin layer over native peers. This is very powerful and allows adapting to every platform.
Another reason why I think Swing does not fit for this purpose is the need in natively-looking UI.
That is a myth. First of all Swing is really close and some platform dependent libraries exist to get it even closer. Also the importance of native UX is exagerrated. Nobody cares if the application is easy to use and valuable for them. Sadly a lot of Swing apps were written by total Java beginners - hence the bad reputation.
@suthcark I think this is a neat idea. IMO, the best way to start with a neat idea is to create a proof of concept. E.g. Implement a simple "hello world" in Swing that runs on TeaVM. It will then be easier for contributors to help you further the project, because they'll be able to see how you implemented those portions.
As someone who has spent a lot of time with TeaVM, CheerpJ, Swing and JavaFX (and SnapKit), I think Alexey is right about this. An interesting test would be to write a dependency generator to find all class/method references in core Swing, then compare against the current TeaVM Java runtime classlib. I think you would find a 1000+ missing classes/methods. By the time you re-implemented these you would wish you had started with the original runtime, like CheerpJ. I remember attending a talk at JavaOne once where the Swing team mentioned that “Hello World Swing” caused a 1000 classes to get loaded and initialized.
I love both CheerpJ/TeaVM, though TeaVM is a better match for my use case. Swing has such a large dependency graph, I don’t think you would ever be able to get the runtime down to a level that would make it look like a competitive web app. Swing always had a (mostly) unfair reputation for being slow, and that would just be re-enforced in the web space. And not just because of the download, but because it assumes so much is synchronous. E.g., if your app loads a lot of images/icons, that all happens synchronously. Swing apps usually assume everything is in a local jar file.
Like TeaVM, I think CheerpJ does an amazing job, but here is a real world example of what we are looking at:
RMStudio CheerpJ Swing: http://www.reportmill.com/cj/RMStudio/RMStudioSwing.html <http://www.reportmill.com/cj/RMStudio/RMStudioSwing.html>
RMStudio CheerpJ DOM: http://www.reportmill.com/cj/RMStudio/RMStudio.html <http://www.reportmill.com/cj/RMStudio/RMStudio.html>
RMStudio TeaVM: http://reportmill.com/snaptea/RM15/rm15.html <http://reportmill.com/snaptea/RM15/rm15.html>
I do grieve at the idea that Java Client in the model of Swing is dying, because Oracle has made such a mess of it, has little interest in it, and has totally abandoned the idea of Java Client on mobile and browser - even as excitement builds for WASM and so many others like Unity are bringing desktop technologies to the web. My personal dream is that someone builds a modern version of Swing (e.g. CodenameOne or SnapKit) and somehow gets serious backing for it along with TeaVM.
Maybe what we should really be trying to do is write a light-weight Swing emulation layer on top of CodenameOne or SnapKit, to provide a reasonable path for legacy apps without being tied down by all the bad stuff.
jeff
By the way, last time I made an effort to measure the numbers looked something like this:
CheerpJ Swing: 80m download (15m compressed) 1+ min CheerpJ Dom: 50m download (10m compressed) 30+ sec TeaVM: 7.6m download (1.2m compressed) 1 sec
It is old. You could also say mature. Tested by millions.
The same can be stated for Cobol :-)
Once it is freed from the JCL and 100% pure Java one can refactor the hell out of it as long as the public API stays intact
The problem is not with implementation, the problem with API, and I can't change it without breaking existing applications.
What makes Swing special is that everything you see is drawn by Swing
AFAIK, Codename One and SnapKit both draw UI. So Swing is not special here.
Also the importance of native UX is exagerrated. Nobody cares if the application is easy to use and valuable for them.
No, I can't agree with this, not by any means. I clearly stated that by "native UX" I don't mean just style of controls, but user experience in general, and it's quite different on different platforms. The UX is different on desktop and mobile because of different display sizes. You can't put many UI elements on mobile since in this case they become small and poorly recognizable; also, it would be hard to use them with fingers. If you adapt mobile UI to desktop, you'll end up with couple large UI elements on entire 24 inch screen, which is also unnatural. Also, there are lots of conventions even on different platforms on desktop, and user gets accustomed to these conventions, so if your application does not follow them, it can't be easy to use.
Can you point me to a couple of specific examples you don't like with Swing?
Well, I don't want to go deep with this, because it seems you just like Swing and on every argument here you will provide counter-argument and this can last forever. So I just leave it here and won't discuss this later.
It's old, therefore it's API is quite cumbersome from the standpoint of modern Java:
- Use of interfaces consisting of constants, while this practice is considered bad. Also, enums can be used instead of integer constants.
- Event listeners are interfaces with several methods, which makes it impossible to fit them into SAM convention, therefore no way to use lambdas.
Also, there are problems of Swing itself (or perhaps, problems of all widget-based toolkits):
- Data tables are hard to use in non-trivial cases. Want some non-trivial cell content? Pain!
- Widget hierarchy is not reflected in code nesting. I believe it's more problem of Java than Swing, and this can be solved in Kotlin. Or this can be solved by describing widget hierarchy with DSL (like XML-based language).
- You have to invent a variable name for every insignificant widget like label or container panel. See previous point.
- You have to apply display properties to each widget individually, no CSS-like mechanism of cascade styling, which is reapplied to widget hierarchy as it changes.
- You don't have advanced capabilities of binding data to UI. What about repeating part of UI for each element in a list (and updating these parts as list changes or content of N-th element of a list changes)?
- No way to include parts of UI into rich text.
Codename One
I don't know CO very well. It has probably a lot of similarities with Swing since its lead dev Shai is an old Swing guy. I doubt though that it has equally powerful widgets built in as Swing does. The main dealbreaker for me was that CO is open source but somewhat only in principle since they force you to use their closed source build servers (and even pay for them if you need not the bare basics). I guess you could set up build servers in principle yourself but you would have to invest a huge amount of work initially - and every time CO changes.
SnapKit
I am not really familiar with SK at all...although I assume it probably also doesn't have as broad a selection of widgets as Swing. Also it is fairly unknown. For Swing you have a lot of developers who know it intimately.
or perhaps, problems of all widget-based toolkits
Yes. Everything complex is not trivial.
It's old, therefore it's API is quite cumbersome from the standpoint of modern Java
Sorry, but your arguments are quite weak. ActionListener and others are SAM. A few are not. Big deal! You can always write a wrapper method that takes a SAM (e.g. Runnable) or even better use method-references. All this syntactic sugar arguments are pretty weak IMHO.
Or this can be solved by describing widget hierarchy with DSL (like XML-based language).
I never saw some XML based UI concept I fell in love with. Sure offer the option, but please also offer UI definitions in 100% code that don't feel weird (I am looking at you Android!).
No way to include parts of UI into rich text.
What?
As someone who has spent a lot of time with TeaVM, CheerpJ, Swing and JavaFX (and SnapKit), I think Alexey is right about this. An interesting test would be to write a dependency generator to find all class/method references in core Swing, then compare against the current TeaVM Java runtime classlib. I think you would find a 1000+ missing classes/methods. By the time you re-implemented these you would wish you had started with the original runtime, like CheerpJ. I remember attending a talk at JavaOne once where the Swing team mentioned that “Hello World Swing” caused a 1000 classes to get loaded and initialized.
I don't see a reason why Swing should be much more complex then SnapKit when run with TeaVM. You only transfer the public API of Swing. The biggest chunk you don't port comes directly from JS. All the code for Paths, Rendering, Fonts, etc. - that's what you already use with SnapKit in the browser. Same complexity.
So when you create a JButton you only need a few Java classes. JButton and its parent classes. The Listener classes and a few more. The code to paint the button on the canvas, to load and display its icon, to load the Font and render its text, to handle its events and all the rest comes from JS. And all that code is already part of SnapKit/SnapTea. You just take the relatively thin public API Layer of Swing (and nothing else) and all the real functionality that public API is using comes from SnapKit/SnapTea.
Just imagine building a JButton on top of SnapKit/SnapTea. It's not that hard. And if you have a JButton the rest of the Swing widgets add nothing new. Same is true for Android.
Only on the Desktop Swing is a big fat cow since it has to implement everything down to rendering a pixel, which already requires probably hundreds of classes.
I don't see a reason why Swing should be much more complex then SnapKit when run with TeaVM. You only transfer the public API of Swing. The biggest chunk you don't port comes directly from JS. All the code for Paths, Rendering, Fonts, etc. - that's what you already use with SnapKit in the browser. Same complexity.
Then you're talking about only implementing a subset of Swing, since all that stuff about paths, rendering, fonts, etc.. is part of the public Swing API. Swing is big. If you start looking at those 1000 classes that Swing brings in, you'll realize quickly just how big its surface area is.
Then you're talking about only implementing a subset of Swing, since all that stuff about paths, rendering, fonts, etc.. is part of the public Swing API. Swing is big. If you start looking at those 1000 classes that Swing brings in, you'll realize quickly just how big its surface area is.
Well, maybe a small subset of Swing is the way to start. It would be probably enough to let 85% of small to mid-size Swing apps run without changes. That subset could always be expanded in the future.
Looks like the Doppio folks reviewed Caciocavallo in 2013 and concluded that it was
- No longer maintained.
- Of questionable quality; [..] could not get the existing source code to work at all.
https://github.com/plasma-umass/doppio/issues/239
I am developing Taishan Office (like MS Office, word/excel/powerpoint) with java(Swing). I compiled whole project to wasm using TeaVM。I am so excited for TeaVM! I have some ideas for you:
- You can try with JWebAssembly and JSweet.
- You can copy swing/awt code to your project, then delete error code, and use graphics function.
I am developing Taishan Office (like MS Office, word/excel/powerpoint) with java(Swing). I compiled whole project to wasm using TeaVM。I am so excited for TeaVM! I have some ideas for you:
- You can try with JWebAssembly and JSweet.
- You can copy swing/awt code to your project, then delete error code, and use graphics function.
Did you do similar things to compile your project to wasm? Is there an online demo one you try to see the result?
@shoeoffhead
- I had compiled whole project to wasm(cost three months), size is about 10M.
- No demo for show. The basement is sample(wasm benchmark).
@shoeoffhead
- I had compiled whole project to wasm(cost three months), size is about 10M.
- No demo for show. The basement is sample(wasm benchmark).
And you can compile Swing to wasm and run it in the browser or how does it work?
Maybe you could make a little video of the convertes Swing-wasm app? Or at least screenshots? Would be interesting to see the Swing UI in action.
@quantum6
1. I had compiled whole project to wasm(cost three months), size is about 10M.
This sounds very cool!
Please send pictures or video.
The TeaVM forum is here: https://groups.google.com/g/teavm
Update 28.05.2023 12:55 Take a look at GWTSwing and maybe give it a shot if you want to stick with a swing like api.
Old Hi, I just wanna share this with you https://github.com/pizzadox9999/Swing-for-TeaVM. It may be a start.