Subscribe: Java Graphics: Code Snippets, Musings, and Discoveries
http://javagraphics.blogspot.com/feeds/posts/default
Added By: Feedage Forager Feedage Grade A rated
Language: English
Tags:
add  article  code  color  component  file  implementation  java  list  model  new  public  simple  source  swing  time 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: Java Graphics: Code Snippets, Musings, and Discoveries

Java Graphics



This blog is being phased out. See the new pumpernickel github project instead.



Updated: 2018-02-18T04:46:23.278-08:00

 



Transition to Pumpernickel

2017-01-19T21:07:52.757-08:00

It's been a good decade, but it's time to wrap up this blog. I'm closing the "javagraphics" project, and I'm transitioning to a new replacement project. The main factors at play (as I see them) are: I enjoy having an open-source repository of personal open-source projects. When writing code: knowing that it's for the public helps me hold myself to a higher standard in terms of code architecture. Plus this repo is a great vehicle to explore topics that complement work-related projects but aren't officially sanctioned by work.All java.net projects are closing soon (in early 2017). So at the very least I have to migrate my repo somewhere else or close it.My focus is no longer on graphics, so the name "javagraphics" makes my new open-source work increasingly off-topic over the years. When I first started this blog, my primary day job was working on Swing apps that included lots of graphics-intensive work. Now my primary job involves databases. I still have opportunities to work on Swing apps (both for work and for fun), but a lot of what I want to work on is not exclusively about graphics.People have started asking for Maven support. When I first started writing open-source projects (nearly a decade ago), my goal was to make really light-weight jars. (So if you wanted my ColorPicker dialog, but not my MultiThumbSlider component: they were separate jars.) But now more than ever: disk space is cheap. What's it to you if you bundle a 300KB jar or a 1MB jar? So before I offered several different downloadable jars, but now I'll more generously group things into different categories. And Maven is clearly the popular delivery vehicle of choice these days, so it's time to catch up with the times.The javagraphics project has always been about cool deliverables; they either offered a compelling new feature or they ran tests demonstrating an impact in performance. Writing up the process in a blog article was mostly an afterthought, and the goal was nearly always to draw attention to the deliverable. The New PlanMy new Pumpernickel project effectively replaces the deprecated javagraphics.java.net repo. In the new repo all my code belongs to the package "com.pump". I migrated most of my code over. Some (old, irrelevant) classes have been purged. For example: I wrote an OptimizedGraphics2D several years ago, but it's no longer useful. In the Pumpernickel project: I want to shift my priorities from maintaining blog articles to just maintaining up-to-date javadoc. This should keep the codebase cleaner and easier to maintain. I still want to include a list of topics (blurbs) on the landing page that summarizes interesting projects. Right now the blurbs still point to my old blogger articles, but over time I want to phase those articles out and only point to thorough javadoc instead. Instead of publishing a unique jar for each project, I grouped code into over a dozen different categories (artifacts): I'd love to tell you I got the Maven implementation flawlessly implemented, but that's not true. This does use a Maven-ish structure, though. If you ask (or help!) I can spend more time on getting executable Maven pom files off the ground. So What About Demos?I really loved that many of the javagraphics projects included simple compelling demos. The Showcase project/artifact is a new stand-alone app that includes a list of demos. It still needs a lot of work. Most of the demos were very crudely ported and dumped into this new app without redesign or cleanup. But it's a start. Do you remember working with Swingset back in the day to explore Swing components? That's similar to what I have in mind for this app. Except it won't ONLY include UI components: it also includes several text-based apps that run tests and measure performance. OK, so now that I say it all out loud: it's hard to explain, and maybe the Showcase app is little too ambitious. I'll let you know how it goes. Everything is up for reevaluation these days. Goodnight and Good LuckI've enjoyed this blog over the years. If I had it to do over again: I wouldn't change a thing. (Well, tha[...]



Desktop Applications: Temporary Files

2016-12-06T19:31:55.660-08:00

This article discusses temporary files, including Java's default model and potential enhancements. Temporary FilesJava comes with a few built-in features related to temporary files: The "java.io.tmpdir" system property. You can access this by calling System.getProperty("java.io.tmpdir"). (It's possible you'll get a security-related exception if your code is executed in a sandbox.)The File.createTempFile(..) method. This creates a file in the right location, but the javadoc cautions: "This method provides only part of a temporary-file facility. To arrange for a file created by this method to be deleted automatically, use the deleteOnExit() method."The non-static File.deleteOnExit() method, which queues your File object for deletion if the JVM exits normally.The "java.io.tmpdir" is obviously important; on all platforms (that I know of) it's the recommended way to manage temp files. But over the years I've developed alternatives to the static File methods, because I think they can be lacking. Here are some of the issues I have with them: Deleting files is expensive and inefficient. The File.deleteOnExit() currently resembles: public void deleteOnExit() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkDelete(path); } if (isInvalid()) { return; } DeleteOnExitHook.add(path); } This ultimately boils down to: Collections.reverse(toBeDeleted); for (String filename : toBeDeleted) { (new File(filename)).delete(); }So we're looping through a list to delete files. If that loop has a few million entries: it's painfully slow.Deleting files is unreliable. The deletion takes place in shutdown hook. (Although it is some sort of special, highly prioritized shutdown hook?) The problem is: shutdown hooks may be arbitrarily cut off. If the OS decides your app is out of time: it's killed. Combine that with what might be a long-running loop and you may have orphaned files. Or what if lightning strikes and you lose power? In that case shutdown hooks won't run at all.These methods lend themselves to files, but not directories. The File.createTempFile method resembles: public static File createTempFile(String prefix, String suffix, File directory) throws IOException { if (prefix.length() < 3) throw new IllegalArgumentException("Prefix string too short"); if (suffix == null) suffix = ".tmp"; File tmpdir = (directory != null) ? directory : TempDirectory.location(); File f; try { do { f = TempDirectory.generateFile(prefix, suffix, tmpdir); } while (f.exists()); if (!f.createNewFile()) throw new IOException("Unable to create temporary file"); } catch (SecurityException se) { // don't reveal temporary directory location if (directory == null) throw new SecurityException("Unable to create temporary file"); throw se; } return f; } After the while loop: we explicitly ask to create the file as a file (see createNewfile instead of mkdir()). ImprovementsThe TempFileManager is an attempt to resolve these problems. It requires explicit initialization (with a unique name), so although it is intended to replace Java's default model: it is not as universally flexible. Although it works out-of-the-box, I'm going to discuss the implementation details in the rest of this section. Suppose your application's name is "Mulligan". Following Java conventions, we might give it a qualified name like "com.myCompany.Mulligan", just to help differentiate it from a competitor's product with the same name. The first thing we do is we create a subdirectory in the temp folder called "com.myCompany.Mulligan". We basically expect ownership of this directory, and we assume no other entity is going to mess with it. Inside the "co[...]



Spinner: Alternative Spinner UI Implementations

2016-02-29T21:58:15.038-08:00

This article discusses a couple new of SpinnerUI implementations. You can download this project here. ContextA couple of years ago I made a dandy mechanism that helped automatically inject sample images in my javadoc. It dumped every screenshot here, using the simple classname to help name it. This made me aware that I had two components with the same name: there were two different classes (used for separate projects, in separate packages) with the name NavigationPanel: Both are useful components, and they're obviously very distinct in appearance. I wanted to keep both, but somehow refactor them to share common logic. My first response was to create an entirely new JComponent named the NavigationPanel and make unique ComponentUI's for it. This automatically required 3 classes: a ComponentUI, a data model, and the JComponent wrapping them all together. On the one hand: the unique NavigationPanel component allowed me to custom-tailor a data model that exactly suited my needs. For example: with a spinner if you want to change the value and the maximum of a SpinnerNumberModel, that triggers two separate events. (Sure, you can get around this by suspending listeners... but that's an unnecessary hassle for such a simple idea.) And if you're at the maximum of the number range, then things get weird. Imagine a list: A, B, C. You have C selected. You want to add an element D and select it. You have to do it in exactly that order (modify list, then select) or you'll get an exception. But if you want to remove element C and select B, then you have to do it in the opposite order (select B, then modify the list) or you'll get an exception. A new data model can let us modify both properties in one call and keep the internal state consistent between events so it's all-around safer to use. These models were also designed around integers, so the data model's method signatures reflected that. The SpinnerNumberModel is a little ambiguous and funky. (That is: it supports Doubles and Integers in a weird look-I-do-everything-at-once kind of way.) And besides that: at any point you can swap out your SpinnerNumberModel with a different SpinnerModel entirely. That's probably a fringe case I shouldn't worry about, but in a more ideal world: I can custom-design method signatures that build in better type-safety up front. (That is: I never have to cast a model to a SpinnerNumberModel.) ... but. On the other hand: using SpinnerUIs has a wider/simpler appeal, because every developer who knows what a Swing UI is has some notion of how to use JSpinners. Implementing this component as a SpinnerUI means other developers can just slap this on with a few lines of code and, if they don't like it, switch it back just as easily. So I'd lose a little type safety and elegance of design, but I'd gain a lot of usability (by developers). ImplementationUltimately I decided to implement this as a SpinnerUI. Hopefully that will be beneficial to both readers of this blog and to myself over time. With that decision out of the way, the next step was to create an abstract parent UI. I name it the NavigationPanelUI to keep it significantly differentiated from your traditional concept of a "spinner". But the basic moving parts are still very similar. This extends the BasicSpinnerUI, and that already has a notion of the next/previous buttons. This class introduces the label and a few special listeners. (Also this implementation disregards the "editor" component. That might be a nice v2.0 feature someday, but it's far outside my current needs for now.) The single-row implementation became the CompactNavigationPanelUI. The only unique logic it needed to add was its own FlowLayout-like layout of all the components. The multiple-row implementation became the LargeNavigationPanelUI. This adds the slider and the first and last button. The first drafts hardwired in the expectation that you'd only ever use this with a SpinnerNumberModel. And probably I should have stopped there and left it as-is (because feature creep will be t[...]



Text: Formatting Source Code in Swing

2015-12-26T20:23:28.015-08:00

This article discusses a text editor written in Java (using Swing) for Java source code. You can download the demo app here. ContextWhat a year it's been! For the last 9 months I've been working at a new job. A database job. Finally: a chance to pick up new skills and leave Swing behind, right? Well, sort of. I guess old habits die hard. Or the positive way to spin this is I'm "bringing my existing skillset to my new role." I'm working on special assignments most of the time, and many of those assignments morph into complex tools to help our team. Having a decent background in desktop apps has turned out to be helpful, and so far I've written 4 mini apps (all in Swing) to help our team automate complex and/or menial tasks. For example: the most recent app helps format source code. My new employer has rigid code formatting standards. (We fail code review if all curly brackets are not on their own line, or if there is not a space between operators and operands.) I'm not going to wax philosophical about when and how teams of developers should embrace stylistic standards, but my argument for automating this process is: dealing with whitespace and easy-to-fix formatting issues is exactly what a computer should be good at, and it's exactly what a human may be bad at. In the last decade we've spent weeks (or months?) of man-hours worrying about these rules through code review, so let's automate this. We have a decent turnover of contractors, so of all the costs involved in bringing someone on board: learning these rules shouldn't be one of them. In this article I'm not going to go into detail about this particular tool, but I'm going to talk about the mechanics of how to present Java source code as in the screenshot above. Java ParsingThe first component we need is a Java parser. Nothing fancy. And we don't need to get a bigger-picture understanding of the code (That is: which tokens make up a method signature? Or which tokens make a field declaration?). Arguably I should have gone fishing for existing toolkits to accomplish this, but this task crept up in scope over time. I didn't realize when I first started out how complex this would grow. My first draft relied simply on regex patterns: public static final Pattern doublePattern = Pattern.compile("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");public static final Pattern intPattern = Pattern.compile("[-+]?[0-9]");public static final Pattern stringPattern = Pattern.compile("\\\"((\\\\\\d{3}+)|(\\\\u\\d{4}+)|(\\\\.)|([^\\\"]))*\\\"");public static final Pattern charPattern = Pattern.compile("\\'((\\\\\\d{3}+)|(\\\\u\\d{4}+)|(\\\\.)|([^\\']))\\'");public static final Pattern wordPattern = Pattern.compile("[a-zA-Z]*(\\w)*");public static final Pattern whitespacePattern = Pattern.compile("\\s*");This was all I needed at first. The original intention for this parser (months and months ago) was just for small inline expressions. Here is a screenshot of the importer tool that helped design imports from speadsheets into our database: But over time the parser creeped up in scope to include method bodies (see that "More..." button?), so we had to add comments: public static final Pattern singleLineCommentPattern = Pattern.compile("//.*");public static final Pattern singleLineAsMultiLineCommentPattern = Pattern.compile("/\\*.*\\*/");public static final Pattern multiLineCommentStartPattern = Pattern.compile("/\\*.*");public static final Pattern multiLineCommentEndPattern = Pattern.compile(".*\\*/");This threw a wrench in simple parsing models, because comments follow complex rules that regex can't easily model. (It's addressable, but right away the code started losing its simplicity/readability.) But as many of you know: regex is slow. As projects continued to creep up in scope, we were passing larger and larger blocks of source code to this parser. For this most recent project (applying stylistic code formatting) we were eventually passing code that could easily be thousands of lines. At one point I plugged in t[...]



Text: Managing a Console in Swing

2015-03-18T10:52:49.268-07:00

This article discusses a possible console implementation using a JTextArea. ContextLately I've been investing a lot of time in polishing up the javagraphics codebase and subjprojects. A handful of these projects are mostly console-based output, so I developed a simple UI to help viewers more easily enjoy them. Existing ModelsConsoles have been around longer than I've been alive, so the idea of engineering a Swing-based UI for console output is nothing new. Before I dive in to my implementation I should survey a few existing alternatives: Redirect standard output streams to JTextArea: this is a simple JTextArea-based model. This is essentially the model I approached this subject with: redirect System.out and System.err to append text to a JTextArea.A simple Java console: starts with redirecting System.out and System.err to a JTextArea and adds a little thread management. It commits the taboo of modifying a Swing component outside of the EDT, but it's a great start.swing-console: This reimagines the Swing component from scratch -- there is no JTextComponent underneath. It handles its rendering and data model on its own. This is beautifully simple, but still packs a nice set of features/methods. Each character can have a foreground and background color, which is something a JTextArea can't do. (A JTextPane can, but those are not as efficient.) But by avoiding a JTextComponent this foregoes inheriting useful features such as clipboard support and accessibility.Message Console: This author was very aware of the different performance implications of a JTextArea vs a JTextPane, so this implementation requires you to choose one or the either.(It's also worth noting the JDK now ships with a jar called JConsole but despite its name that is unrelated. Also in Java 1.6 the Console class was introduced to help you interact with existing consoles -- but it is not a UI component itself.) My ImplementationI also leaned towards a JTextArea-based approach. I used a modest approach (like the first link above) for years, but recently I decided I wanted these additional features: thread safety, multiple colors, and assistance in setting up tables. The result is a class called the BasicConsole. Also to help layer the architecture: my console will create PrintStreams by calling console.createPrintStream(..). This immediately lends itself to redirecting System.out and System.err, but it also helps with color management (see below). Thread SafetyEach PrintStream the BasicConsole creates may be accessed from any thread, but it ultimately wants to modify a Swing component on the EDT thread. If there are competing simultaneous strings coming in: there is no defined "winner" when it comes to whose output gets displayed first. The BasicConsole achieves thread safety by synchronizing around a queue of insertions: public void append(String s) {   synchronized(pendingInsertions) {     pendingInsertions.add( new Insertion(s) );     if(!SwingUtilities.isEventDispatchThread()) {       SwingUtilities.invokeLater(clearQueue);       return;     }     clearQueue.run();   }}The clearQueue.run() method then leads with: public void run() {   Insertion[] array;   synchronized(pendingInsertions) {     array = pendingInsertions.toArray(new Insertion[pendingInsertions.size()]);     pendingInsertions.clear();   }   for(Insertion r : array) {     ...   }}Multiple ColorsSome of the articles I listed above point out that a JTextArea is a no-frills text component that doesn't support character attributes like a foreground color. This means it is fundamentally impossible to color System.err output in red as I'm used to seeing in the Eclipse console. However: all JTextComponents support Highlighters, which can be used to render under the text. The most obvious implementation here is simply as a solid background color -- that's wha[...]



Sliders: Creating a Slider with Multiple Thumbs

2015-01-24T12:27:18.911-08:00

This article discusses a new JComponent that resembles a JSlider with multiple thumbs. You can download this component here. ContextActually it's not entirely true to say this is a "new" component. In 2008 I created the a concise GUI component to manipulate multiple-color gradients: the GradientSlider. As an afterthought I separated part of that logic so the GradientSlider was a subclass of the MultiThumbSlider. But the parent class was abstract, and the GradientSlider was the only implementation. About 6 years later someone reached out to me inquiring about the MultiThumbSlider, so I decided to flesh it out and help it live up to its potential. That nugget of history will come up again later on when it comes to certain implementation details. IntroductionFirst: is a new component necessary? Is it possible to just manipulate a JSlider to achieve the desired functionality? Not really. The JSlider class has methods built-in that assume the data model you're referring to is a single number within a fixed range. We could add methods called getValues() and setValues(), but that's a kludgy implementation that's begging for someone someday to misunderstand the API. Eventually someone will cast the JComponent simply as a JSlider and not our special subclass, and more mistakes will be made. In an ideal world the best response might be to dismantle the JSlider so it supports multiple thumbs, but that's out of the question here. (Anyone want to form a committee to revise javax.swing classes?) Next: do we have to create a new ComponentUI, too? Is there a way we can leverage existing look-and-feels to do our heavy lifting for us? This would be amazing for two reasons: We're lazy, and this would be less work.This would automatically update itself when a new L&F is used. Whether you're using a 3rd party L&F, or whether Apple/Microsoft redesigned the look of normal sliders: this would just naturally fit in.So I tried this approach. Here is a quick/rough implementation. (Nevermind for now what it is subclassing.) public class EmulatingMultiThumbSliderUI extends DefaultMultiThumbSliderUI { JSlider normalSlider = new JSlider(); BasicSliderUI bsu = (BasicSliderUI)normalSlider.getUI(); public EmulatingMultiThumbSliderUI(MultiThumbSlider slider) { super(slider); int mid = (normalSlider.getMaximum()+normalSlider.getMinimum())/2; normalSlider.setValue(mid); slider.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { copySize(); } }); slider.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { copyAttributes(); } }); copySize(); copyAttributes(); } private void copySize() { normalSlider.setBounds(slider.getBounds()); } private void copyAttributes() { normalSlider.setOrientation(slider.getOrientation()); normalSlider.setPaintTicks(slider.isPaintTicks()); } @Override protected void paintTrack(Graphics2D g) { bsu.paintTrack(g); if(slider.isPaintTicks()) bsu.paintTicks(g); } @Override protected void paintFocus(Graphics2D g) { bsu.paintFocus(g); } @Override protected void paintThumb(Graphics2D g, int thumbIndex, float selected) { Point2D center = getThumbCenter(thumbIndex); g.translate(-normalSlider.getWidth()/2, -normalSlider.getHeight()/2 ); g.translate( center.getX(), center.getY() ); bsu.paintThumb(g); }}The BasicSliderUI has public methods for painting the thumb! Just iterate over each thumb and translate the Graphics as needed, and voila! It's a wonderful theory. And it's such a shame it doesn't work. Just because the BasicSliderUI offers those promising methods doesn't mean they are implemented. And when they aren't implemented, all we get is the gray blocky implementation from the BasicSliderUI: The size of the thumbs and other details might be navigable obstacles, but it's obvious that we're not actually leveraging the Aqua L&F here. The L&F over[...]



Text: Handwriting Text Effect

2014-11-26T23:18:23.375-08:00

This article discusses an animation model that mimics text written by hand. The application is discusses is available for download here (source code included). ImplementationThe goal of this project is to provide a text effect to make the presentation of special text subtly more memorable. Originally I explored a calligraphic style of writing, but the more I explored this idea the more I decided a casual style looked better. This project was actually shelved for several months because I got mired down in one crucial detail: copyright. Since I'm not a graphic designer I didn't want to create a new font from scratch, but all the fonts I wanted to emulate were the intellectual property of other artists (or companies). Luckily (for a separate project) I recently became much more familiar with fonts and font licenses, and I stumbled across several beautiful hand-written fonts. One of them was Comic Neue -- a tasteful replacement for Comic Sans that is released as public domain. Armed with Comic Neue as my template, I created my own version to render as a hand-written text effect. My copy is only the skeletal frame of the letter -- the stroke thickness and style are not included. Also in my copy the direction/progression of the shape path matters, because the shape will be traced in the original direction as it is redrawn for the user. The UI was a straightforward extension of an existing UI relating to editing cubic Bezier curves, and the actual effect largely built on existing tools that iterate over a shape in increments. On the right is a screenshot of the tool I developed to edit the written font. It's very rough around the edges (no menus, no undo, and it has a few bugs), but it was never intended for mass use. It edits files that map characters to shape data (like this). StructureEach glyph is expressed as 1 pixel tall with an arbitrary width. Usually the width is less than the height (except for very long characters such as 'w' or 'm'), so it helps to think of the glyph as living inside a unit square -- except for the width. The written font container is mostly a map of characters. It contains a few extra properties, such as: Descent: the descent, as expressed as a fraction of the ascent. (If the baseline is the line the letter "a" sits on, then the descent is the space below the baseline reserved for letters like "j".) For example: a 20-pt font may simply treat the ascent as 20 pixels, and if the descent is stored as ".2" then it is calculated as "20 px * .2". Leading: the leading is similarly expressed as a fraction of the ascent. (The leading is the vertical space between one row's descent and the second row's ascent.) Median: this line in the middle of the ascent is a visual marker to help the glyph for "a" and "m" reach approximately the same height. Style: either "plain" or "calligraphy", this is deemphasized for now because I don't have a compelling calligraphic example. (The hard part of the calligraphy model is already implemented, though.)The result is depicted here: The calligraphy font works too, although I'm disillusioned with the final effect it produces. I haven't implemented as many characters in this font: (The calligraphic font I'm writing by hand, based on books about calligraphy. It's easier to develop the Comic Neue font because I'm mostly tracing an onion skin.) JavaScript AdaptationDid you see the splash Barbie has made in the headlines recently? In 2010 Matel released a book that was somehow supposed to encourage girls to work with computers, but it had surprisingly anti-feminist undertones. After a scathing editorial went viral Matel has apologized and pulled the book. Meanwhile some entrepreneurial developers created a write-your-own-version website (and smartphone app!), and the story has been "fixed" (and parodied) several times over. So here I copied one panel from the Feminist Hacker Barbie website to demonstrate a JavaScr[...]



Shapes: Intersection of Two Cubic Bezier Curves

2014-11-26T23:25:46.665-08:00

This article discusses a mathematically-elegant-but-impractical approach to identifying the points where two cubic Bezier curves intersect. Specifically this identifies an 18th degree polynomial whose roots identify the t-values of intersection(s). ContextThis problem first came to my attention in college, and it haunted me for years after that. At least two people much better at math than myself told me it couldn't be done. For some reason I convinced myself that this was worth pursuing, though, and eventually I figured it out. That was around 2008. I was disappointed with the ultimate results and shelved this project, but now when I google the question I see more people are interested in it: so I'm posting what I found here for posterity. The MathThe derivation itself is discussed in mathematical terms in this paper. In my opinion the most exciting nugget in this paper is page 5, which reads: This is probably a well-known method to some readers, but I enjoyed the bittersweet thrill of discovering it for myself. Armed with this plus more well-known cubic formulas: it's possible to create a single polynomial equation that identifies the t-values (relative to one of the two curves) where there are intersections. The ProgrammingWhile it is mathematically possible (and many academics will call it easy) to do this it is not trivial computationally. I had to create a small package of classes to symbolically represent these expressions and manipulate everything. At its peak complexity this equation is 42,000 terms long, although in the PDF referenced above I heavily factored it so it can be represented in about 50 pages. I kept running into memory errors (although of course it took a lot of time to reach them), and so I had to experiment for days with possible performance tweaks. But at times my approach was also flawed, so I may have made calculations more complex than necessary. If I had consistently had a flawless approach then maybe performance would have been less of an issue. The program that made the calculations is available here (source code included). This app does two things simultaneously: It writes the heart of the PDF above.It offers a UI that lets you manipulate two bezier curves and see their intersection.Preparing this paper also led me down the rabbit hole that is LaTeX: very neat stuff. I needed to write a lot of mathematical formulas, but I wanted it to be done tastefully. As usual: smarter and more motivated people have come before me and laid down a great framework for what I needed to do. All of my symbolic math classes include an option to specify the output format (normal plain text or LaTeX text). ConclusionI do not recommend using this approach, but I'm glad I explored it. Once I understood the complexity of the equation involved: I immediately doubted its possible application in an environment already filled with rounding error. As other sources point out: a better solution is a "recursive subdivision [that] exploits convex hull property of Bezier curve and usually checks intersection of bounding boxes of curve segments". (See the answer by MBo; I think the answer by Stochastically is less complete.) I've implemented this approach separately (not discussed here); it's faster and I would assert it makes more sense. Imagine a 2D binary search -- you very quickly get a high degree of precision, and you can immediately abort once you realize two rectangles don't intersect. It's also worth noting that my polynomial solution identifies all t-values relative to one of the two cubic curves, so if you require the t-value from the other curve then you still need more information. (Which is yet another reason why a numerical subdivision is better!) Also remember you only want t-values between [0, 1]. And you may get false leads where t2=.5 (good!), but it corresponds to an intersection where t1=9 (bad!): so it actually is[...]



Documentation: Annotation, Doclets and Taglets

2016-01-10T17:41:21.108-08:00

This article explores different practical uses of annotations, doclets and taglets. Specifically this discusses how the subprojects in the javagraphics codebase are cataloged, and this discusses how to automate adding screenshots to javadocs. ContextOnce every so often I try to revisit the build process for this blog. The model I currently use is hand-made. In hindsight: I should have invested in an existing tool, but when I started this blog in 2007 I didn't see a great option -- and I didn't realize how sophisticated build tools would be in 5-10 years! Gradle didn't even exist yet, and I hadn't heard of Maven (although when I googled it: it turns out it has existed since around 2004). The only tool I was familiar with was ant scripts, and that seemed like more trouble than it was worth. My primary exposure to ant was through work, and there we decided to use Fat Jar, which seemed like a nonstarter for this blog since my objective was to build minimally small jars. So I made my own tool (shown on the right) with its own simple UI. It's proven so useful over the years that I have yet to find a compelling reason to replace it. This manages the landing page for this project, the online javadoc, and the jars. It does have to be invoked manually, but that's more of a feature than a bug: since I don't differentiate between beta releases and final releases I don't want every SVN commit to trigger a rebuild of everything. (Plus I generally work on this blog on my personal computers, so I don't want a 5-15 minute build script to hog my CPU while I'm working.) While I can click "Select All" and run everything: usually I only rebuild specific jars/projects as needed. But without completely replacing this tool: I wanted to look around to see if there ways to make it smarter. This includes revising existing logic and adding new features. Doclets and AnnotationsOne thing I wanted to focus on is how the landing page is written. Each entry on that page is considered a "blurb". They all have a title, summary and date, but they are not required to map to a jar or even an article. Some map to the main landing page, and some map to a separate page of scrapped projects. So there's a variety of blurb types and formats. This seemed like a perfect use of an Annotation. I wrote the Blurb annotation to express this meta information, and added it to every class that deserves its own entry on the landing page. That much seemed easy/obvious, but the next question was: how do I iterate over every class to identify which classes have blurbs? My original approach was: Iterate over every source file. Identify the class name (which is a combination of the package name and the file name -- because inner classes never had their own blurbs). Use Class.forName(derivedName) to refer to the appropriate Class object. Use reflection to see if that class had a Blurb annotation.(Note: the annotation has to be preceded by @Retention(RetentionPolicy.RUNTIME) for reflection to pick it up as expected! That was frustrating to figure out.) But while researching something else: I realized the doclet tool handles steps 1 and 2 more accurately. So I asked some friends, "Hey, what do you know about doclets? I'm thinking of writing my own." Their response was generally, "Um, isn't that a dead technology from a decade ago?" Even after explaining that doclets are still very much in use (the "javadoc" that we know and love/tolerate is the most popular instance of a doclet): they remained unconvinced that this was worth my time and energy. Their cynicism is partly why I decided to write this up as a blog article -- I want to advocate for doclets as a useful annotative/analytic build tool. The IndexBlurbsDoclet is the class that I use now to build the landing page. Iterating through all the relevant classes to create the two blurb summary pages is now reduced to [...]



Images: 3D Transitions and PerspectiveTransforms

2014-05-01T12:15:08.240-07:00

This article describes a couple of simple 3D transitions, how to render a BufferedImage with a PerspectiveTransform, and offers a case study in ways to optimize an algorithm. Special thanks to Werner Randelshofer, who suggested up to half of the ideas and talking points in this article. You can download the resulting code (source included) here. ContextOver 5 years ago I shared a set of transitions that extended the abstract class Transition2D. I don't have exact metrics, but that article is probably one of the ten most popular articles I've written. Recently a client commissioned a similar set of 3D transitions: cube and flip. In this context, what is the difference between 2D and 3D? The main distinction has to do with how images are transformed. The Transition2D architecture was designed to be restricted to Java 2D. This means it only supports AffineTransforms. This is a nuanced topic, but the simplest overview is: an AffineTransform can be created from exactly 3 corners. The 4th corner is always automatically derived from the other 3. Because of this: an AffineTransform can only be used to transform a rectangle into a parallelogram. It can be rotated and it can be sheared, but it remains a parallelogram. To achieve a 3D effect we need another type of transform: the PerspectiveTransform. This transform can be created using any 4 corner points, so this is necessary to create the trapezoid we usually associate with 3D perspectives. (However this transform is not limited to trapezoids: we can use any irregular quadrilateral.) But this is much harder to render, so it wasn't part of the Java 2D architecture. (It was, however, part of JAI.) Implementing a PerspectiveTransform in JavaMy first task was to identify a model to render a PerspectiveTransform. Originally I tried to borrow the PerspectiveFilter from www.jhlabs.com. This threw an exception when the transform had corners that were outside the destination image, so that was a nonstarter. (I could try to fix it, but that would require developing such intimate knowledge that I might as well write it myself.) I knew this task was relatively simple to do, so in about an hour I rolled out the first version of the BasicImageContext. But the devil is in the details: I spent the next week or so optimizing it. (In my opinion: the first draft should always focus on readability and abstract modeling, but once you're convinced that you have an accurate implementation there's usually something you can do to optimize it.) I cataloged 12 different optimizations (see BasicImageContextDemo and the accompanying results here). The final draft was over 5x faster than the original. Here are the optimizations, in order of importance: Reduced time to 28%: Multithreading. By breaking up the job into tiles, each tile can be rendered in a separate thread.Reduced time to 80%: Inline expansion of PerspectiveTransform.transform(). While the JVM can perform some inlining during runtime at its discretion, in this instance we know this very simple method is going to be hit hard several million times. We get a significant advantage by copying and pasting that small method body into our innermost loop.Reduced time to 85%: Only iterate only relevant pixels. Originally I calculated the bounding box of the affected area and iterated over every pixel in that rectangle, but with a couple of linear functions I can target the scan more accurately. Reduced time to 88%: Use a one-dimension array of pixels. My original implementation used a 2D matrix, but a single array reduced the amount of of bounds checking and look-ups.Reduced time to 96%: Reduce the number of conversions between primitives. Reduced time to 97%: Inline expansion of Math.min. Even inlining a 1-line function made a noticeable difference.Reduced time to 97%: Reduce the number of shift right operations.[...]



Performance: Constructing Arrays and Images

2014-04-13T23:29:31.188-07:00

This article explores performance implications of repetitively constructing arrays and images. ContextFor years at work we've used a static look-up table to cache certain images and primitive arrays, because at some point in the last decade I became convinced this made a huge difference in performance. However I was surprised at the performance I was seeing on a new project without this architecture: maybe my assumptions about wanting to recycle arrays and images are outdated? So I wanted to crunch some numbers and see how things look in a modern JVM. ImplementationThe ResourcePool is a new class that caches arrays and BufferedImages for reuse. Whenever you request an object, it first checks to see if a cached copy is available. If it is: the cached copy is returned. If it isn't: then a new instance is created. So the ideal usage pattern is: int[] data = ResourcePool.get().getIntArray(10000);try {   doSomething();} finally {   ResourcePool.get().put(data);}In theory you can create custom ResourcePools and pass them around, but for now the static get() method returns a global instance that meets all of my current needs. But if we only ever store objects, then this has the potential to turn into a memory leak (depending on how it is used). So there are 3 separate constraints used to safeguard against this: Time Limit: each object has a time limit, and every few seconds ResourcePools are polled to check for expired resources. This time limit is generally expected to be a few seconds. (The default is around 5.) Total Cache Size: this is the number of objects of a given type that this object keeps strong references to. This is applied per category (int, float, double, long, short, byte, and BufferedImages). Targeted Cache Size: resources are grouped not just by category but by target dimensions. (For example: int arrays of 100 units are separate from int arrays of 200 units.) This limit is significantly smaller than the total cache size: it indicates how many resources of a certain size we'll keep in memory at a time. For BufferedImages this limit is by default very low (around 5); it is dangerously easy to cache a few dozen 800x600 images and burn through dozens of megabytes of memory.The target use case here is for highly repetitive tasks, but in architectures where you can't necessarily predict when the caller is finished using a service/operation. So in a series of image filters -- such as blur operations -- it might be useful to repeatedly reuse the same int arrays and BufferedImages, but after a period of a few seconds it's safe to say the CPU-intensive work is over. And at the end of the day: it's not a problem to reconstruct new resources. Garbage collection will clean up after us in a reasonably efficient way. The question is: are we better off recycling these objects, or is construction such a trivial expense that this extra architecture is more of a liability than a time-saver? Performance TestsThe ResourcePoolDemo is a minimal app that times a few thousand operations and prints the comparative figures. You can click through the javadoc to see the source code. Here is the output from that app: OS = Mac OS X (10.9.2), x86_64Java Version = 1.7.0_17Image Comparison:Paint Clear Construction (ms) ResourcePool (ms)true true 482 452true false 482 438false true 38 22false false 33 1Primitive Construction (ms) ResourcePool (ms)int[] 31 0float[] 35 0long[] 68 0double[] 65 0Scaling Test:Array Size ResourcePool Construction Percent10 928.0 82.0 1131.71%100 96.0 71.0 135.21%1000 11.0 42.0 26.19%10000 1.0 64.0 1.56%100000 0.0 64.0 0%1000000 0.0 69.0 0%The image tests include a couple of additional variables: paint: indicates we made a simple paint operation to the BufferedImage. clear: (only applicable to the Reso[...]



Shapes: Modeling Cubic Shapes without Complex Input

2014-03-27T04:17:19.851-07:00

This is article offers a new data structure and UI for defining a shape.

This is one of three articles that offers a UI for defining a shape. (The others are here and here.) You can download an app that explores all three models here.

Context

I wanted the user to have some control over the points used to define a java.awt.Shape, but CubicPath (and accompanying CubicPathCreationUI was too advanced.

While looking for alternative models: I took a liking to the freehand shape mode in Google Doc's drawing tool. In that UI the user click to add nodes, and they were automatically smoothed out to create a curved shape.

Implementation

The CurvedPolyline is a straight-forward implementation of this model. The data structure is just a series of java.awt.Point2Ds (with methods to add/set) points.

The real magic occurs when you asked this shape for its PathIterator. Here each point calculates the angle between its neighboring points and uses that as its own tangent slope. This is based loosely on the mean value theorem: it's the only slope that we know is necessarily guaranteed to exist between the adjacent points, and it's generally a reasonable guess that that's the direction a user wanted to the slope to be. (There are other ways we could guess, and this guess may not always be perfect, but it's a solid start.)

Here is a screen recording testing out this model:

(image)

Conclusion

I like this basic idea (that is: the idea that the tangent slope is the slope of the neighboring points), but the strength/magnitude of the tangent slope could probably use some refining. In saying that I might have just mixed metaphors a little bit. Saying "tangent slope" and "mean value theorem" invokes images of a y(x) function, but when we convert this to a shape we're actually using Bezier control points and parametric graphs. The distance the controls points are from the node reflect the strength/magnitude of the tangent slope, and that's the behavior I might want to tweak.

On a sidenote, do I have any readers in London who might like to grab a coffee/pint this week?




Gradients: Avoiding Color Banding

2014-03-24T03:24:35.844-07:00

This article explores a solution to color banding in linear gradients. You can download this project here. ContextAnother recent subproject (the DecoratedPanelUI) really highlighted a known problem: gradients of similar colors tends to introduce color banding. It's tempting to believe color banding is a thing of the 1990's (with 256-color monitors), but even outside the world of gifs: the problem still exists today. Most displays these days support "millions of colors", but usually that simply means they support 3 channels (red, green, and blue) at 8 bits per channel. 8 bits guarantees 256 (28) unique values, so with three unique channels that comes to 16,777,216 colors (2563). Here is an animation that demonstrates banding. At 0%: the left and right sides of this animation are the same color (130, 190, 220). By 100%: the right side of the gradient has changed to (130, 160, 180). If you look closely you can see blocks of color sliding from right-to-left: Although we have millions of colors are our disposal: this gradient is limited to about 20. (Sometimes this may be hard to detect with the naked eye; I'll provide more insightful tools below. If you're viewing this on a laptop: tilting the display forwards or backwards can also help highlight the problem.) I see this all to frequently on televsion: whether it's Roku or Hulu or the opening credits of a movie, if the gradient uses highly similar colors, then there might be some color banding. Aside from not being a true gradient, banding is also going to introduce the contrast effect between two adjacent bands, which can further throw off viewers. But this shouldn't be too hard to resolve. In previous articles I also explored error diffusion and rendering gradients as TexturePaints, so all I need to do now is mix all this logic together. That is: I want to apply diffusion to an image that represents a gradient, and then use that image as a TexturePaint. ImplementationThe problem exists enough that I can notice it, but in order to avoid eyestrain: the first thing I need to do is add a tool to help identify the problem. Normally I'd lean on the MagnificationPanel, but in this case I can do better. This method will provide striking contrast when pixel values change: /** This mods each color component by two and then amplifies that * value to show when pixel values change. * @param source the incoming image * @param dest the image to store the new representation in. */private void zoom(BufferedImage source,BufferedImage dest) { int[] row = new int[width]; for(int y = 0; y 16 ) & 0xff; int g = (row[x] >> 8 ) & 0xff; int b = (row[x] >> 0 ) & 0xff; r = (r%2)*(256/2); g = (g%2)*(256/2); b = (b%2)*(256/2); row[x] = 0xff000000 + ( r [...]



Implementing a JThrobber

2014-03-23T02:54:39.016-07:00

This article presents a JThrobber implementation and a few accompanying UIs. (This is a remake of an older article.) You can download this project here. IntroductionAlthough this isn't one of my more popular articles: this is about a component I use in well over half my apps these days. (Which is to say: I think this is important, even if nobody else does!) My previous implementation (5 years ago) was a simple SliderUI. That choice was probably inspired by Apple's original Java implementation in Technical Note 2196: setting the client property "JProgressBar.style" to "circular" for an indeterminate JProgressBar. But really: masking this as a SliderUI is sloppy. It deserves to have its own Swing component. So although it is minimal and near-functionless (it has no special actions or listeners to speak of): this article presents this component as a JThrobber. (There is already a JThrobber out there in the wild, but with no downloadable files it looks like it might be unfinished or inactive?) I don't like the name "throbber", but as someone pointed out in my previous post on this subject: that's a previously adopted naming convention. (Besides, what else would I call it? "Spinner" is obviously a nonstarter...) Wikipedia defines a throbber as: A throbber is a graphic found in a graphical user interface of a computer program that animates to show the user that the program is performing an action in the background (such as downloading content, conducting intensive calculations or communicating with an external device). In contrast to a progress bar, a throbber does not convey how much of the action has been completed. Usually the throbber is found on the right side of a program's toolbar or menu bar. The form the throbber takes varies, but it is common for it to be the logo of the program it is part of. Most of the time the throbber is a still image (known as its resting frame), but when the program is performing an action the throbber begins to animate in a loop to let the user know that the program is busy and has not frozen. Once the action is complete, the throbber returns to its resting frame. Normally, it is possible for the user to continue interacting with the program while the throbber is animating (one such possibility may be to press a stop button to cancel the action that the program is doing). Clicking on the throbber itself might perform some specific action (for example go to the program's website, pause or cancel the background action).So I suppose I could add an ActionListener to the JThrobber to react to mouse clicks, but their description about a logo doesn't resonate with me. (In fact: it sounds a little 1990's? I'm sure some apps may still include a logo, but I don't think I've seen an app behave this way for quite a while.) I would rather my throbbers be a looping animation that doesn't have a resting state -- it is simply hidden when it is not in use. Maybe I'm relating more to the component Apple calls an "Asynchronous Progress Indicator": An asynchronous progress indicator provides feedback on an ongoing process. Asynchronous progress indicators are available in Interface Builder. In the Attributes pane of the inspector, select Spinning for the style and be sure the Indeterminate checkbox is selected. To create an asynchronous progress indicator using AppKit programming interfaces, use the NSProgressIndicator class with style NSProgressIndicatorSpinningStyle. Appearance and BehaviorThe appearance of the asynchronous progress indicator is provided automatically. The asynchronous progress indicator always spins at the same rate. GuidelinesUse an asynchronous progress indicator when space is very constrained, such as in a text field or near a control. Becau[...]



Panels: an Improved PanelUI

2015-03-15T21:22:09.091-07:00

This article presents a new PanelUI to achieve a variety of customizable looks. You can download this code or run the demo app here. ContextI've found the UIs and borders that come standard with Java a little bit lacking. For example, consider the simple screenshot on the right. If I want a panel with subtle rounded edges and a slight shadow towards the top: there isn't a good way to achieve this with the default Swing UIs and borders. (See BevelBorder, EtchedBorder, LineBorder, MatteBorder, SoftBevelBorder, StrokeBorder, and TitledBorder.) Of these the SoftBevelBorder might come closest to emulating the screenshot to the right, but it doesn't let you customize the angle of the incoming light, the number of bevel shades, or how rounded the corners are. A few years ago I wrote the DecoratedPanel to meet this need, but it was amateurish: it was a JPanel, but it needed to be a PanelUI. Because of this: the border rules were funky, and in rare cases the panel repaints could be buggy. The DecoratedPanelUI is a remake of that idea, incorporating bits of old code in a new architecture with new features and fewer bugs. ImplementationOne key difficulty in implementing this panel UI is the separation of a JComponent from its Border. In this case: they need to be rendered together to guarantee continuity, but they are necessarily rendered separately. So the DecoratedPanelUI resolves this by introducing a Renderer that processes all the rendering. The Border paints using the Renderer object with a clipping that punches a whole in the middle of the panel, and the DecoratedPanelUI paints using the Renderer but clips away the border. So you can provide your own customized Renderer to override certain behaviors, and it will affect both the panel UI and the border. The border, now that it is separated from the panel UI, can be used in complete isolation from a DecoratedPanelUI. (That is: it can be used on any JComponent.) Both the border and the panel UI store a collection of key/value pairs that are interpreted by the Renderer. Whenever possible: I tried to make these attributes floats to facilitate tweening and variable degrees of precision. The DecoratedPanelUI's javadoc includes some examples of different preset looks that I'll restate here: The more over-the-top something is the more it should be used with care: so the "plastic" look should be used sparingly. But sometimes it can add some much-needed panache. At work, for example: we needed to display a placeholder graphic when a plug-in was missing. Just displaying a warning icon, a broken image icon, or something similar was OK, but wrapping it up in a plastic-y panel made it look much more professionally done. Similarly on Hulu: boxes are never simply empty -- they have a light glaze/glare on the (in the upper-left). All over you'll see a light reflection (positioned in various ways) is a common tool to invoke imagery of a polished 3D look. However when it comes to a more everyday necessity: you'll probaby want a more subtle look. The brushed metal look I threw in just to demonstrate how a custom Renderer could be used to spice things up. That's a very peculiar look, and as of this writing (2014) it's very dated: Apple introduced this about a decade ago and phased it out over 5 years ago. (Read more here.) But my point is: if you have specific needs (or whims) you can make drastically different renderers that still generally plug into this architecture. Some possible inspiration might be found here. See the javadoc for more screenshots and discussion of features. Also the jar that accompanies this article includes a set of complex controls to experiment with UI configurations: ConclusionI didn't start [...]



Panels: Refreshes and Transitions

2014-06-02T00:51:18.201-07:00

This article explores a panel that can refresh itself using a Transition2D. A demo app is available here. ImplementationThe actual new code this project introduced is less than 2 hundred lines (and that includes javadoc!), but I think it's such a handy tool that it deserves its own article and demo. In separated articles I've presented two different architectures for transitions: Transition2Ds and Transition3Ds. The new TransitionPanel lets you refresh its contents with one of these transitions. The TransitionPanel itself uses a CardLayout that shows one of two panels: The body: this panel is accessible via getBody(), and is at your disposal to configure however you choose. The transition panel: this is only made visible during a transition. Because this replaces the body nothing in the body is capable of receiving user input during the transition.The transition is kicked off when you call TransitionPanel.startTransition(). This takes a before and after snapshot of the body (which changes because you pass a Runnable as an argument to startTransition()). Also (not shown in graphic): I added swipe support to this demo. In Java, swiping is generally supported as a MouseWheelEvent automatically. This is not part of the TransitionPanel itself (which has no concept of "forward" and "backward"), but it is part of the TransitionPanelDemo. This is a surprisingly tricky concept: in the example above it's easy to conceptualize this as a scrolling list. The mental model/illusion is so convincing that it's easy to forget that there is only 1 panel with a JLabel that changes based on occasional Runnables (not a ListModel). Since the current implementation simply starts a transition (it has no model for controlling or altering a transition once it began): you can't abort or undo a transition based on whether a swipe gesture was interrupted, reversed or incomplete. So this is a valuable feature, but it is not as intuitive feeling as scrolling through a JList. ConclusionWhile it is definitely possible for flashy effects and animations to detract from the user experience: when used in moderation they can be helpful to the user, and they offer a professional/polished look to your application. In 2007 when I first released the Transition2D classes: it wasn't safe to say that the majority of computers could offer a sufficiently high frame playback rate to make .25 s animations play smoothly. But now that's increasingly less of an issue, and those animations are increasingly the norm. (Especially for smartphones: my smartphone uses a pivot transition for browsing tabs, a zoomed-fade-in transition for opening apps, a simple fade transition to leave the locked homescreen, and push transitions to swipe around large lists. I'd have a harder time finding something that isn't animated than finding something that is!) Already I can tell one key feature that's missing here is the option to control how the animation tweens from 0-1. (For example: accelerating, decelerating, both, bounce, etc.) So a future version might include support for this. But for the time being: this should be simple enough to plug into existing UIs to spruce things up a bit.[...]



Panels: Collapsible Sections

2014-06-02T00:48:48.130-07:00

This article explores a model to partition a panel into sections and to collapse those sections on demand. You can download a sample implementation here.Partitioning SectionsI had a specific look and feel in mind for my end goal, but the idea of separating a container into sections needed to be abstracted into its own layer first. The SectionContainer is the simple abstract model that defines a series of Sections.I struggled for a while to articulate exactly what distinguishes a "section" from a java.awt.Component, and similarly: what separates a SectionContainer from a java.awt.LayoutManager. So to clarify, here are some possible implementations:The implementation presented below, which is a vertical series of labelled panels.Similar to a CardLayout: this might show exactly 1 panel at a time (with or without a text label).Similar to a JTabbedPane: this might show one panel, and include additional features (such as a close control, contextual menus, drag-and-drop reordering, etc.)Similar to floating panels in a JLayeredPane, such as Apple's implementation of widgets.So this is a model that is somewhere between a LayoutManager and a ComponentUI. The SectionContainer addresses this by storing a series of Sections, and it is up to subclasses to come up with a meaningful presentation of those sections.Collapsible SectionsRight now I'm wanting to make an inspector-style series of vertical sections. Specifically:Each section should be clearly labeled with a header.Each section should be collapsible by interacting with the section header. Collapsing should be animated.The CollapsibleContainer class (see animation to the right) implements all headers as JButtons, and organizes all Sections with a private LayoutManager that identifies which sections are meant to be collapsed or expanded (and animates the UI accordingly).The current implementation relies on vertical weights, similar to a GridBagLayout. When you add a section: you can define an optional vertical weight for that section. All the available (visible) weights are added together, and extra vertical is distributed accordingly. (If the weight is not defined, it is assumed to be zero.) In this way you can let some sections stretch to fill all the vertical space.ConclusionFor now this is sufficient, but there's a lot of possible improvements I'd like to add.In addition to a weight-based layout, I'd like to present a priority-based model. In this model: sections can claim and integer-level priority, and the highest-ranking (visible) sections get all the remaining vertical height (distributed equally). This way certain sections would always outrank the next type of section, but there would be a tiered hierarchy model to decide what gets priority.Also, as mentioned above: this will probably be my ideal vehicle to approach sophisticated browser-level tabs someday. (The JTabbedPane was great a decade or two ago, but now we generally expect tabs to have a close button, an icon, a contextual menu, etc.)[...]



Images: Color Palette Reduction

2014-06-02T00:48:18.655-07:00

This article provides a crash course in how to reduce the color palette of an image in Java without using JAI (or any other non-standard classes). This includes a demo app that you can download here.BackgroundSince the dawn of computer science: color reduction has been an important subject. So important that we can't simply call it "color reduction": we have to call it "color quantization". This naming convention seemed a little bit over-the-top at first, but I suppose if I had dedicated a lifetime (or at least a doctoral thesis) to this subject, then I would want it to have a sophisticated name too.I cannot stress enough how vast the related body of work on this subject is. In 1993 an international consortium devoted to standardizing colors across devices formed. But about a century before that the CIE formed to explore the representation and reproducibility of color (as well human perception of color). For example: the common HSB representation of a color is generally based on the Munsell System from around 1898. Just ask anyone at Adobe how thoroughly scholars have explored color perception, representation, and quantization over the years. All that is to say: if you're an expert in this field then I apologize in advance for butchering your work in this article. But if you're an amateur then you might find this is a good jumping off point.The reason I'm tackling this now is: I need a gif encoder. This is partly because I'm going to rework many of my articles to feature animated gifs instead of applets. (Because regressing in technology is always the right thing to do! Don't get me started on my rant about applets, jnlp and security). And I want complete control over the encoding process -- something I don't think I can achieve with JAI. For example: I'm going to want to be able to apply error diffusion across a repeating image tile (that is: the seams of the tile shouldn't stand out because the diffusion didn't wrap-around). Also I'm going to want very fine control over the level of compression. But those will have to come later: first I need color quantization to build on.ImplementationFirst I needed a simple mechanism to store information about color frequency. The ColorSet class maintains a simple map of RGB colors (represented as a 24-bit integer) to their frequency (also represented as an integer). Instead of using the PixelGrabber model (which always creeped me out because it required a UI component at construction), I applied the IntARGBConverter from previous projects to pipe incoming pixel data into the data structure. (Last I checked: this is more memory efficient and faster than the PixelGrabber.)My broad goal is image quantization. There are some algorithms that approach this holistically, but I chose to implement it in distinct stages: first I want to pick a new color palette (via color quantization), then create a new image using that palette (image quantization).The most popular approach to color quantization appears to be the median cut color reduction algorithm. This is a beautifully simple clustering algorithm: just sort the list according to reds, then split in half and sort by greens, then blues, then reds again, etc. With each split: you also cut the target number of colors in half. When you get to the point where you only have 1 target color: take the average all the colors in your list. I modified this slightly to account for the frequency of colors (so if we have 100 occurrences of red and 1 occurrence of orange: then the red receives 100x more weight), but otherwise this model is hard to improve on.The next step is image quantization. The[...]



Navigation: Breadcrumbs

2014-02-08T07:09:04.514-08:00

This article explores a Swing implementation of breadcrumbs.BackgroundBreadcrumbs are a very common navigation tool these days. Although they are more common in websites (which require a complex hierarchical structure), it is certainly possible a desktop application can require them too.My original need had to do with navigating a complex tree representing the local file system. To maximize window real estate: the tree could be hidden after a file was selected. But I still wanted to show the basic path of the selected file, so breadcrumbs seemed like the natural way to do it.Other ExamplesThe most fundamental examples of breadcrumbs I can think of (outside of websites) are used in navigating the file system on both Mac and Windows.On Windows 7 the file path is visible by default. It is positioned towards the top of the window--very similar to the URL field in a browser. However on Windows they've done some clever programming: this serves as both a series of immutable directories that you can click and right-click to interact with and it can transform to a normal text field if you try typing in it. In this way: advanced users can instantly type complex paths instead of using the UI to navigate there. (Again: similar to a browser.) In fact there is very little difference in a breadcrumb and a file path. The difference is that the breadcrumb is a UI component, and the file path is an abstract entity. In a model-view-controller approach: the file path is the model and the breadcrumb is the view. You could alternatively represent a file path as a JComboBox (similar to command+clicking the document name in a window title on Mac), or as a plain text field for advanced users. On Mac this control is called the "path bar", and it is not visible by default. (It is accessible via the "View" menu in the Finder.) Each element is clickable, and right-clickable, but unlike Windows: there is no way (that I know of) to use the path bar to enter a directory location. (Users can press command+shift+G to navigate to a particular path.) This is typical of Apple's design: it shows a clear separation of power users from intermediate users.ImplementationMy primary goal is to emulate Apple's model. Someday I might want to add the ability to type (like the Windows model), but for now that is outside my needs.The JBreadCrumb is the Swing component that models this data. It can be parameterized to whatever you want the crumbs to represent (Strings, Files, etc.). The only things of interest in this object are:The method void setPath(T...): to define the current path The method T[] getPath(): to retrieve the current path The BreadCrumbFormatter: to customize how the breadcrumbs are formatted. This is similar to a ListCellRenderer for JLists, although it does not produce a stamp-like component.The hard work is all implemented in the BreadCrumbUI class. The current implementation creates a child JLabel for each crumb, and positions them as necessary. We leave enough room for a triangle icon between each crumb. Here is a screenshot featuring the JBreadCrumbDemo app (available here, source code included):The top breadcrumb uses the default configuration, but the bottom breadcrumb is an example of ways you can customize the look of this component.Of course a really useful breadcrumb shouldn't just be a static painting: you should be able to interact with it. With a NavigationListener you can listen for single-clicks and double-clicks and react appropriately. This does not yet take into account right-clicks or drag-and-drop. Special ConsiderationsThe above examples are great[...]



ComboBoxUIs and PopupFactories

2014-02-04T21:41:14.526-08:00

IntroductionI recently wanted to experiment with creating my own ComboBoxUI. Using the FilledButtonUI model as a starting point: I created the FilledComboBoxUI. (See the demo here.) It wasn't as straight-forward as I'd expected it to be: but the current draft weighs in at only 500 lines of code. Unfortunately this highlighted a bug regarding applets in many browsers: JPopupMenus would be positioned relative to the top-left corner of the display, and not the applet. The result is that you would click a combobox and the popup menu would appear several pixels above and to the left. The same problem was also observed for tooltips. To the right is a screenshot of this bug in the Wordle applet: although I clicked the "Font" menu, the popup that displayed is several pixels away from where it should be. SolutionAfter a couple of hours of experimentation: I gave up trying to reposition the heavyweight popup. Instead: as a work-around I decided to try displaying the popup as a lightweight component. It's not very common that we need to use the powerful complexity of the JLayeredPane: but it has the potential to display JComponent above everything (it even has a layer specifically designated for popups). Originally my goal was only to implement a lightweight model for my new FilledComboBoxUI class (because I had such explicit control over how the popup would be invoked), but as I rummaged around I realized the javax.swing.PopupFactory is an existing architecture that may let me intercept all popups (including tooltips). The final result is the new AppletPopupFactory (source here). After you invoke the static initialize() method: it will handle all popups. If a popup is requested outside of an applet: then the original PopupFactory is used instead (so if it's invoked in an application vs an applet: then the fancy new code isn't touched). Additional problems included: Originally for the new PopupFactory I tried calling JPopupMenu.setVisible(..) to help control visibility, because it is still a JComponent. Unfortunately: this is a complex invocation that ultimately defers to the current PopupFactory. The result (if I try to use setVisible(..)) is a recursive loop that never actually alters visibility. The solution was to simply avoid interacting with the visibility. (The JPopupMenu is a strange creature, and now I know it can function as a normal lightweight JComponent as long as you don't touch its visibility.) Instead: adding it and removing it from the parent JLayeredPane can achieve the necessary effect. Clicking outside the popup needs to dismiss the popup. So behind the popup: we install a giant invisible panel that consumes MouseEvents. This means we notice when the user clicks in this area (so we can hide the popup), and we prevent the user from clicking any other component while the popup is visible. The popup generally rendered correctly, but it needed decoration. By "decoration" I mean: a border and a shadow. The shadow is more of an indulgence, but I'll explain it first: since we already have a giant panel used to intercept MouseEvents: I tweaked this so it rendered a small shadow around the popup. The border proved a stranger problem: when the AquaComboBoxUI was being used on Mac 10.7.5 (Java 1.7): the border was never rendered. It was correctly defined as a simple LineBorder -- and the same LineBorder rendered correctly with the FilledComboBoxUI -- but with the Aqua model it never appeared. The (strange) work-around here was to remove the border and render it along with the shadow in the background pane. This is[...]



Thumbnails: Formatting Thumbnails

2014-06-15T20:08:04.808-07:00

This article discusses how to tastefully format/decorate a thumbnail. Previous articles discuss how to scale images efficiently, including bmps, jpgs and pngs, and how to extract existing thumbnails from large jpg images, but this article focuses on the question: and then what?ContextWhy do we need to decorate thumbnails? We don't need to, I guess. This is a matter of taste. For comparison, here are a few examples of what other people are doing: Mac OS FinderThis is a set of thumbnails when I browse a folder of images in the Finder on Mac 10.7. This is one of the most complicated formatting I've found: it includes a shadow, a white border, and then a thin dark border.iTunesIn iTunes: the thumbnails only have a light shadow. Here you might be able to make more assumptions about the content of the thumbnail: it is probably a very brightly colored image with lots of eye-catching patterns and texture. (That is: an artist specifically composed this thumbnail to fill every pixel.)Woot.comWoot.com doesn't bother with shadows, but they still add some very distinct borders around certain thumbnails. In this case: the borders help identify what is the "clickable area" for these thumbnails.AmazonThese non-rectangular thumbnails from Amazon.com have no shadows or borders at all. These are also the largest thumbnails in this set of examples: they occupy so much space that they are visually distinct without any help from formatting. Microsoft.com also appears to follow this model (using large, undecorated thumbnails).The decision regarding when and how to decorate a thumbnail might be better left to graphic designers than to software engineers, but for now my point is simply: this is an established convention that you may sometimes want to follow. OverviewMy most immediate goal is to create a file browsing UI, so I want to emulate the first example shown above: photo thumbnails in the Mac Finder. There are three basic elements in this image: the drop shadow, the border, and the thumbnail itself. I wrote a demo app that navigates each layer. Here is a gif that cycles through the inspector for each: This jar (including source code) is available here. This application demonstrates the BasicThumbnail class and its ability to format a thumbnail image. The default options displayed are the preset options that resemble the Mac OS thumbnail (simply referred to by the static field BasicThumbnail.Aqua). Each layer of the thumbnail (shadow, border, image) is a separate object with its own concept of padding (insets). They are painted in the order shown in the list (from left to right), so that each layer overlaps all the previous layers. To modify a layer: click that layer in the list and use the controls in the inspector. All layers support varying amounts of curvature for the corners. A curvature of zero is a sharp (rectangular) corner, and a high curvature is a very rounded corner. ShadowIn this model a shadow is just a series of strokes of increasing thickness. (That is: a shadow of 1 pixel, then 3 pixels, then 5 pixels, etc.) Each stroke is solid black with a very light opacity (usually less than 20 out of 255). Since this can be several pixels thick: you have control of both the inner and outer curvature. BorderA border is a solid-color frame. Technically this can use any color, but the UI here restricts it to a shade of gray for simplicity's sake. Like the shadow: this supports an inner and outer curvature. ImageThis layer contains the actual thumbnail. It also contains an optional background color, an[...]



Lists: An Observable List for UIs

2013-06-30T13:38:15.792-07:00

This article discusses combining the java.util.List interface with the javax.swing.ListModel interface. That is: suppose you want a list that you can easily interact with, but also that plugs into UI elements. The Simple SolutionThe simplest solution is to implement these two interfaces in one object: public class MyList implements java.util.List, javax.swing.ListModel { ...}Several years ago I wrote the WatchableVector with this approach in mind: this class extends the java.util.Stack, so all the data structure logic is built-in. All this class has to do is add support for the listeners. This list can be plugged directly into a JList, and at the same time you can treat it like it a traditional java.util.List. For example, now if you call java.util.Collections.sort( myList ), the UI will automatically update. ShortcomingsAfter working with this class for several years, I started to identify shortcomings in this implementation: Recursive Listeners. In theory a a observable/observer contract is simple: when a change occurs, then notify the listeners. But in the world of UI: it is my experience that listeners spiral out of control very quickly. Here is a simplified/approximated stack trace diagram of a potential listener problem: Here the list is represented in blue, and two separate listeners are represented in orange and green. The first listener (orange) is notified that a new file is added to a list, but it knows the list needs to always be alphabetized: so it resorts the list. This ends up triggering the first (orange) listener a second time before the second (green) listener ever hears about the first event. If the second listener actually listens to the described event: it will be confused that elements are being reordered that it doesn't even know exist yet. This is a contrived example showing a simplified chain reaction. In the real world the first listener might have interacted with a separate data structure, and that structure interacted with another, and another, and as a result: a series of listeners that seemed minimally simple (even elegant?) on paper turn into a nightmare of events. I refer to this as "cascading listeners", but a coworker refers to it as "listener hell". The Event Dispatch Thread. My ListModel is plugged into a Swing component: so it needs to only ever be updated on the event dispatch thread. But my List is the same as my ListModel: so complex (potentially time-consuming) operations on my list now need to occur on the EDT, or ambiguous "bad things" may happen (in a hard-to-pin-down kind of way). Multithreading. Consider the illustrated example above: all this is occurring in the event dispatch thread. What happens if another thread wants to access this list? It has to wait, because the call to WatchableVector.add(..) is synchronized, as is the call the WatchableVector.get(index). The operation itself may be relatively fast, but the synchronization lock isn't released until all the listeners have been notified. (Including the potentially recursive listener chain reactions...). If you think of this as an IO-model: there's no reason other threads have to wait to read data from this list while other listeners spin their wheels -- but we should prevent them from write operations.This weekend I wrote a new class to address these issues: the ObservableList. Addressing Listener RecursionThe ObservableList continues to support the ListDataListener, but it separates listeners into two categories: synchronized and unsynchronized. Synchr[...]



ListUIs: Adding Decorations to Cells

2013-05-27T23:46:41.177-07:00

This is a follow-up to my previous article: TreeUI's: Adding Decorations to Cells.What is a "Decoration" again?A decoration is a UI component overlayed inside or on top of another component. Muted-color minimal buttons/decorations are becoming increasingly common in modern UIs. This is great way to add extra functionality for power users without adding too much visual clutter. Here is a screenshot of part of my current Firefox window. There are 6 decorations showing: The star bookmarks a page. The down arrow presents a list of recent URLs. The circular arrow refreshes the page. The left side of the search field lets me change search engines. The word "Google" is also a decoration indicating what search engine is being used. The right side of the search field commits my search.... but there are only 3 non-decorative UI elements showing: the URL field, the history button, and the search field. The decorations add a lot of subtle controls in a small space. As an accessibility side-note: it's worth mentioning that decorations usually do not receive keyboard focus as you navigate the interface with the tab key. They are second-class citizens when it comes to your window hierarchy. You probably need to provide alternate ways to access these features (menu shortcuts, for example) to help reach a wider target audience. List DecorationsThe section above talked about decorations in general, but what are some examples of decorations for list elements? Above are search results in a recent youtube query: when you mouse over a thumbnail there is an optional button to add a video to your queue. Also you could provide buttons to delete list elements, reload, or show progress indicators. On the right is a new-ish decoration for sound files observed on Mac OS 10.7. When you mouse over the graphic: a play button fades in. When you click the play button: the outer ring appears, and the gray arc proceeds clockwise representing the playback of your sound. The same playback controls are used for movies, however for movies the controls fade away as soon as you mouse out of the preview area. (Traditionally these controls have been presented with a thin horizontal row of controls along the bottom of a sound/movie. I'm not trying to argue that Apple's new circular timeline is any better than a horizontal timeline: both could be presented with overlayed controls.) ImplementationIn Swing, JLists (and JTrees) use renderers, where one component is rubber stamped for every element in the list/tree. This is a great scalable model (because tens of thousands of elements can safely be rendered without too much overhead), but it lacks mouse input. To implement decorations on a list, I developed the DecoratedListUI. This UI manages multiple ListDecorations, which are rubber-stamp overlays to your existing ListCellRenderers. All you have to do is invoke the following: ListDecoration[] arrayOfDecorations;...myList.setUI( new DecoratedListUI() );myList.putClientProperty( DecoratedListUI.KEY_DECORATIONS, arrayOfDecorations);ExampleHere is an example that emulates the Mac playback controls with a list of 5 sounds: You can download this jar (source included) here. (Note: usually I make an effort to keep my jars small in file size so you can easily plug them in to other projects, but in this case: I ended up bundling several megabytes of wav files inside the jar. So while this jar is nearly 2 MB, the code you need is probably less than 100 KB. Sorry for the inconvenience[...]



TreeUIs: Adding Decorations to Cells

2013-05-27T23:46:49.654-07:00

This article discusses a modified TreeUI that lets you add decorations on the right side of your tree. (See this other article for a similar discussion focusing on JLists.) What do I mean by "Decoration"?The short answer is, "I'm not exactly sure." It's similar to a button or a label (depending on which one you want), and that's how most users will perceive it, but it is not actually a JComponent, and it does not exist in the Swing hierarchy of your window. In a JTree: every cell is rendered via a TreeCellRenderer. The same renderer is consulted for every row in the tree, so the intended usage is for one component to be used to display potentially thousands of different values. This is referred to as "stamping", because the renderer is repeatedly painting to the tree without actually belonging to it. This is a wonderful design regarding memory use, but it becomes difficult to add functionality to trees the same way you can add functionality to text fields and other Swing components -- because you don't have a solid grasp on the hierarchy of elements involved. The decoration model partially addresses this issue. Swing components are (usually) very well suited to this kind of augmentation. There is nothing sacred about the current implementation of the JTree and how it renders: these components are designed to flexible and, when possible, improved to meet your needs. ExamplesTo help paint a better picture of what I'm describing, here is an applet demonstrating tree decorations: This applet (source code included) is available here. Here is a summary of each decoration: Progress Indicator: the root node takes a few seconds to load. While it is loading: a progress indicator appears on the right side of the tree. As soon as the tree is fully loaded: the indicator is hidden. Refresh Button: Once the progress indicator is dismissed, the root node will show a refresh button when it is selected. (When clicked, the node re-loads like it did before.) Play/Pause Buttons: when the "Playable" node is selected a play/pause toggle is present. (In this demo nothing actually plays, but this was designed with audio playback in mind.) Warning Indicator: this node shows a pulsing warning icon when selected. (Thanks to the Silk icon set for the image!) Rating Stars: this node shows 5 rating stars when selected. This is a good demonstration of the current limits of the decoration implementation: clicking and dragging does not work like I would want it to. Delete Button: this removes the selected node from the list.The delete button is actually the original motivation for this project: I didn't want the user to have to click a tree node and then navigate somewhere else in the UI to the delete button. In my case this saved several pixels, cleaned up the layout, and made the user's task more efficient. Also because the button is adjacent to what it modifies: there is little room for confusion about which object the user is acting on. However I am also worried that this model can introduce too much visual clutter (aka "over-stimulation"). To limit the amount of controls the user needs to process I made most of the decorations only appear in a row when that row is selected. Also this helps guard against accidentally clicking the wrong button, which becomes increasingly important when your controls become smaller. Restraining the number of decorations is just a suggestion, though: you can make all your decorations visible all th[...]



Text: Swivel Animations

2014-06-06T17:25:44.856-07:00

This article replicates a fun animation that uses carefully timed pan-and-zooms to highlight certain content. ContextI just wrapped another great year at SXSW. As expected: after 5 days of back-to-back sessions I'm exhausted, my brain is full, my feet are sore, and all the wonderful innovative ideas I have bubbling up inside won't really see the light of day at work because, well, pesky reality keeps getting in the way. They always encourage you to tweet during SXSW sessions. Sometimes moderators actually refer to the tweets during each session to redirect the conversation or answer questions. During one session instead of presenting slides or a close up of the speaker: the projectors simply showed live tweets. But they were all at right angles to each other, and the camera swiveled around to focus on each one. I wish I knew exactly what program did that (can anyone tell me?), but I decided I wanted to achieve the same effect. The PlanWhat I want to focus on right now is the core of the animation: manipulating AffineTransforms to zoom in, out, and swivel around a large static canvas. To achieve this I started with a minimal interface: public interface TransformAnimation { /** * * @param progress a float within [0, 1]. * @return the AffineTransform for the argument. */ public AffineTransform getTransform(float progress,int viewWidth,int viewHeight);}The piece that followed was also pretty straight-forward: the SwivelPathAnimation is the animation I was looking for. The class itself is very small, but it took a few days to develop because I was trying to develop the UI at the same time. (What good is the animation without a way to test it?) You construct the animation with a series of Highlight objects. These highlights have a center, a width and height, and an angle of rotation. So if you think of this animation as moving a camera around a page: this controls the placement, zoom and rotation of the camera. Each highlight also keeps track of its duration. When you construct a SwivelPathAnimation you also define the default swivel/transition duration: so each highlight can have its own unique duration, but it's assumed all your transitions should be the same duration. The path the camera takes is automatic. It is guaranteed to cross the center of each highlight, and it my sincerest hope that it will do so gracefully (without wild curves or excessive detours). This draws on several other articles relating to working with bezier shapes, including this one, possibly this one, and most definitely this one. Deep inside the animation are controls that ration out the timing as needed. The animation doesn't stop moving when it's displaying a highlight: it just slows down to a very slow speed. Then when it's time for a transition the speed picks back up again. Here is a sample of the finished product: An error occurred displaying this video. You can download the applet (source included) hereConclusionThere is a slight visual aliasing issue when the text (which is stored as a giant Shape) very slowly moves at an angled direction, but I don't know if that's something we can ever fix. Overall this worked out as I'd hoped, and I'd like to keep dabbling with similar effects in the future. Also I'd like to point out that everything in this project (except a few generics and enums) is compatible with Java 1.4 which was written just over a decade ago (in February of 2002). My point is:[...]