Developing inexpensive UI prototype in html
In January we started to build an experimental Samebug plugin to IntelliJ IDEA. While IDEA uses Swing, we didn’t have much experience with Java GUIs and it soon turned out that the learning curve for Swing is too steep for us for a sandbox project. I’ll tell you how we cheated the system and built our prototype without digging deep in Component Layouts and Look and Feels.
How did we get here
Previously, our workflow with Samebug looked like:
- Execute some code in IDEA, see a crash
- Copy the stack trace
- Open samebug.io and paste the stack trace
- Search solutions
We found that leaving the IDE and opening a browser disrupts the developer’s workflow. We decided to integrate Samebug into the IDE, this way our users can search and see solutions in their development environment. JetBrains has plenty of resources to make plugin development easy and we knew that Swing has a component that can render html, so how hard could it be? Our plugin UI will be a single JEditorPane, showing the same content as our web page and that’s all, integration solved.
Naturally, when we tried it and showed our page via JEditorPane, it was a complete disaster. We had to realize that it support HTML3.2 (labelled as ‘cutting edge’, erm, back in 1999), so we had to make several more-or-less trivial adjustments to get it work.
- Relative addresses are not handled. We noticed it when the images not showed up on the page, and the CSS was missing. Switching to absolute urls fixes this problem, or you can workaround both image and CSS loading.
- You can set the CSS separately, so you can use a local CSS file instead of downloading it at each reload.
JEditorPane htmlPane = new JEditorPane();
HTMLEditorKit htmlKit = new HTMLEditorKit();
StyleSheet ss = htmlKit.getStyleSheet();
- HTMLEditorKit caches the images and you can also abuse this cache to use local images.
- StyleSheet does not understand the concept of CSS classes, does not split the class name by whitespaces. With this snippet below, ‘kittens’ would be red, but ‘fluffy kittens’ would be not, because that tag is interpreted not to have the matching class.
<span class=”solution best”>fluffy kittens</span>
- We found faster to rewrite the page with <table>s instead of fixing it with all those alignment, margin and padding problems of this handicapped CSS.
- For interactions, you have to set a HyperlinkListener. Using a custom HyperlinkListener you will have a total control over what happens when the user click on a link.
Don’t push it’s limits too far
At this point, we were pretty happy with the results. Developing so far was relatively cheap and we got a functioning prototype in a few days. However, it was also clear that going further this way would be a dead end, as we hit some nasty bugs and had problems that were estimated too expensive to solve.
- You can access and modify the DOM, but without selectors it’s just painful. If you want to change something, you either reload the whole content, or start taking Swing lessons.
- You cannot use the same html code here that was already written for the web, there is always something messed up. It’s not a problem until you are just prototyping, but actually it means that you have to support a severely crippled browser from the previous millennium.
- Rarely we have seen unexpected behaviors during development, e. g. the image size attributes were ignored and the image was shown without scaling. We have never gone after these elusive bugs, it is possible that the problem was in our code, nonetheless these experiences made us certain about abandoning the html UI as soon as possible.
After all, I think JEditorPane + html was a good choice for UI prototyping. We had experience with html, but not with Swing and this way we could experiment a bit with the Samebug plugin while keeping the development time low, winning more time to learn Swing. At the end of the day, cheating won’t take you anywhere; you have to take the hard way.