It’s finally time to release one of my favorite new skins for Swing applications. The latest 4.0dev drop of Substance provides full support for a new dark skin named Magma. Like Nebula, Nebula Brick Wall and (partially) Business Black Steel, it uses a mix of dark and light color schemes, but takes this one step further. In Magma, the default and disabled color schemes are dark, and the active (selected, pressed, armed, rollover) color schemes are light (saturated Sunset shifted to red). In addition, like Autumn, it uses the same color scheme for the default and disabled states, and defines a custom alpha value (translucency) for the disabled state. The end result (see screenshots below) is that the disabled controls appear less “visible” as the default controls. This also means that the watermark “shines through” the disabled controls (look closer at the disabled buttons in the first screenshot below).

Here are a few screenshots of different controls under the new Magma skin. Buttons, toggle buttons, checkboxes and radio buttons in different states (default, selected, disabled and disabled selected):

Comboboxes in different states (default, active, disabled, with custom background):

An internal frame with a few controls:

Horizontal and vertical sliders in different states (enabled, disabled, ticks, labels, RTL). Note the translucent layers on the disabled sliders:

Progress bars (horizontal, vertical, determinate, indeterminate, with caption):

Tree with a selected and rollover path:

A control panel with different controls embedded in a SwingX task pane:

SwingX error pane:

SwingX month view:

A frame with menubar, toolbar and status bar from SwingX:

You’re welcome to try this skin and report any issues / RFEs that you find.

This also marks the core feature freeze stage for the 4.0 version of Substance. From this point on, only the user-requested features, minor polishments and bugfixes will be done on the main trunk. Since version 4.0 introduces binary incompatibilities with the previous release, you’re welcome to follow the instructions in the migration guide in order to migrate to version 4.0 (in case your application uses Substance-specific APIs and client properties). The final release is planned for September 4th.

You can run a test WebStart application by clicking the button below. The application is signed and requires read-only access to the local disk (for the filetree). In order to switch to Magma, go to the Skins menu and select “Magma”.

Year of the Desktop Linux

July 12th, 2007
    
<font color="#7f0055"><strong>import </strong></font><font color="#000000">java.awt.*;</font>
<font color="#7f0055"><strong>import </strong></font><font color="#000000">java.util.Calendar;</font>

<font color="#7f0055"><strong>import </strong></font><font color="#000000">javax.swing.*;</font>

<font color="#7f0055"><strong>public class </strong></font><font color="#000000">YearOfLinuxDesktop </font><font color="#000000">{</font>
<font color="#ffffff">  </font><font color="#7f0055"><strong>private static class </strong></font><font color="#000000">YearOfLinuxDesktopPanel </font><font color="#7f0055"><strong>
        extends </strong></font><font color="#000000">JPanel </font><font color="#000000">{</font>
<font color="#ffffff">    </font><font color="#646464">@Override</font>
<font color="#ffffff">    </font><font color="#7f0055"><strong>protected </strong></font><font color="#7f0055"><strong>void </strong></font><font color="#000000">paintComponent</font><font color="#000000">(</font><font color="#000000">Graphics g</font><font color="#000000">) {</font>
<font color="#ffffff">      </font><font color="#000000">Graphics2D g2d = </font><font color="#000000">(</font><font color="#000000">Graphics2D</font><font color="#000000">)</font><font color="#000000">g.create</font><font color="#000000">()</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">g2d.setColor</font><font color="#000000">(</font><font color="#000000">Color.white</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">g2d.fillRect</font><font color="#000000">(</font><font color="#990000">0</font><font color="#000000">, </font><font color="#990000">0</font><font color="#000000">, getWidth</font><font color="#000000">()</font><font color="#000000">,
           getHeight</font><font color="#000000">())</font><font color="#000000">;</font>

<font color="#ffffff">      </font><font color="#000000">g2d.setColor</font><font color="#000000">(</font><font color="#000000">Color.black</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">Calendar calendar = Calendar.getInstance</font><font color="#000000">()</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">String str = </font><font color="#000000">(</font><font color="#000000">calendar.get</font><font color="#000000">(</font><font color="#000000">Calendar.YEAR</font><font color="#000000">)</font><font color="#000000">
        + </font><font color="#990000">1</font><font color="#000000">)</font><font color="#000000">+ </font><font color="#2a00ff">
        " will be the year of Linux desktop"</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">g2d.setFont</font><font color="#000000">(</font><font color="#000000">g2d.getFont</font><font color="#000000">()</font><font color="#000000">.deriveFont</font><font color="#000000">(</font><font color="#990000">20.0f</font><font color="#000000">))</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">FontMetrics fm = g2d.getFontMetrics</font><font color="#000000">()</font><font color="#000000">;</font>

<font color="#ffffff">      </font><font color="#000000">g2d.setRenderingHint</font><font color="#000000">(
          </font><font color="#000000">RenderingHints.KEY_TEXT_ANTIALIASING,</font>
<font color="#ffffff">          </font><font color="#000000">RenderingHints.VALUE_TEXT_ANTIALIAS_ON</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#3f7f5f">// The following is safe to call on Linux
      // as well</font><font color="#3f7f5f"> since the rendering is done in
      // Java and not with</font><font color="#3f7f5f"> native APIs.
</font><font color="#ffffff">      </font><font color="#000000">g2d.drawString</font><font color="#000000">(</font><font color="#000000">str, </font><font color="#000000">
          (</font><font color="#000000">getWidth</font><font color="#000000">() </font><font color="#000000">- fm.stringWidth</font><font color="#000000">(</font><font color="#000000">str</font><font color="#000000">)) </font><font color="#000000">/ </font><font color="#990000">2</font><font color="#000000">,</font>
<font color="#ffffff">          </font><font color="#000000">(</font><font color="#000000">getHeight</font><font color="#000000">() </font><font color="#000000">- fm.getHeight</font><font color="#000000">()) </font><font color="#000000">/ </font><font color="#990000">2</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">g2d.dispose</font><font color="#000000">()</font><font color="#000000">;</font>
<font color="#ffffff">    </font><font color="#000000">}</font>
<font color="#ffffff">  </font><font color="#000000">}</font>

<font color="#ffffff">  </font><font color="#7f0055"><strong>public static </strong></font><font color="#7f0055"><strong>void </strong></font><font color="#000000">main</font><font color="#000000">(</font><font color="#000000">String</font><font color="#000000">[] </font><font color="#000000">args</font><font color="#000000">) {</font>
<font color="#ffffff">    </font><font color="#000000">SwingUtilities.invokeLater</font><font color="#000000">(</font><font color="#7f0055"><strong>new </strong></font><font color="#000000">Runnable</font><font color="#000000">() {</font>
<font color="#ffffff">      </font><font color="#7f0055"><strong>public </strong></font><font color="#7f0055"><strong>void </strong></font><font color="#000000">run</font><font color="#000000">() {</font>
<font color="#ffffff">        </font><font color="#000000">JFrame frame = </font><font color="#7f0055"><strong>new </strong></font><font color="#000000">JFrame</font><font color="#000000">(</font><font color="#2a00ff">
          "Linux on Desktop is here!!!"</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">        </font><font color="#000000">frame.add</font><font color="#000000">(</font><font color="#7f0055"><strong>new </strong></font><font color="#000000">YearOfLinuxDesktopPanel</font><font color="#000000">())</font><font color="#000000">;</font>
<font color="#ffffff">        </font><font color="#000000">frame.setSize</font><font color="#000000">(</font><font color="#990000">400</font><font color="#000000">, </font><font color="#990000">300</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">        </font><font color="#000000">frame.setLocationRelativeTo</font><font color="#000000">(</font><font color="#7f0055"><strong>null</strong></font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">        </font><font color="#000000">frame.setDefaultCloseOperation</font><font color="#000000">(
             </font><font color="#000000">JFrame.EXIT_ON_CLOSE</font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">        </font><font color="#000000">frame.setVisible</font><font color="#000000">(</font><font color="#7f0055"><strong>true</strong></font><font color="#000000">)</font><font color="#000000">;</font>
<font color="#ffffff">      </font><font color="#000000">}</font>
<font color="#ffffff">    </font><font color="#000000">})</font><font color="#000000">;</font>
<font color="#ffffff">  </font><font color="#000000">}</font>
<font color="#000000">}</font>

I’m reading the very thorough overview of the “IDE shootout” that took place a few days ago (thanks, Kirk, for summing it up for all those who couldn’t be there), and the following is simply unbelievable:

The next question Aizatsky addressed was why IntelliJ isn’t open source. “Open source is all about the opportunity to contribute back to the project,” said Aizatsky. “But honestly, how many people have ever produced a custom build of Eclipse? I think no one, no one here (at least).”

That is a very interesting definition of open-source. A pity that it’s as far from the reality as the marketing would like you to believe. There’s so many things wrong with it that i don’t even know where to begin.

By taking the literal meaning, “open source” means that the source to your product is open to the general public. You can put restrictive terms of what can be done with that source (think GPL, read-only or even “open and you’re tainted forever” license), but the code is open. Which means that if i want to see how it works, i can. Now, this doesn’t mean that i necessarily want to change it, recompile and redistribute it. Maybe i want to see how it works because i want to learn from the best. Maybe i want to see how it works just to take this one method and use it in my project (if i follow the licensing terms). Maybe i’m stuck with my plugin and i want to see how it works from the inside instead of browsing other plugins and hope that somebody was smart enough to figure it out.

And no, the Early Access Program is not a replacement for opening the read-only repository to the public (or even publishing a tarball). Early Access Program is a cheap and easy way to get a lot of bugs found out before your paying users start complaining about a new version that is unstable. And forums – tried that and didn’t get any answer (that was back in 2005 and things may have changed, but i never bothered coming back when my original requests for help were largely ignored). Give me the source code and i’ll figure it out on my own (hopefully). I did it with NetBeans, i should be able to do it with IntelliJ. But don’t **** me about people not wanting to contribute back to the main trunk being the main reason for not open-sourcing it.

This is the third part in the ongoing series about advanced animations on core Swing component built-in to the latest binary drops of Substance look-and-feel.

  • The first part showed rollover and selection background animations on menus, sliders, tables and table headers
  • The second part showed rollover foreground animations on menus under a skin that uses dark background fill on menubars

This part is going to show rollover and selection background and foreground animations under a mixed dark-light theme. A few weeks ago I have added a few experimental skins to Substance, and two of these (Nebula and Nebula Brick Wall) use the colors from the upcoming Nimbus look and feel. The design of Nimbus is interesting in that it uses dark highlight color schemes on trees, tables, lists and menus:

This presents an interesting problem once animations will be added – you have to fade not only the background (from white to dark blue), but also the foreground (from black to white). Here is how these animations look like under the Nebula skin in the latest 4.0dev drop of Substance. The first video shows rollover animations on menus and menu items (under the default speed setting):


The second video shows rollover and selection animations on a tree (note that both background and foreground colors are animating):

The third video shows rollover and selection animations on a list:

The last video shows rollover and selection animations on a table (and its header). Note how the settings (foreground / background) of a custom cell renderer are respected during the animation sequences:

So, you’re welcome to grab the latest binary drops of version 4.0dev and try the new and improved Nebula and Nebula Brick Wall skins.