Mac Widgets for Java – 0.9.1

September 14, 2008

Java Unified Tool Bar
Java Bottom Bar
I just released Mac Widgets for Java version 0.9.1. I’ve added official support for the Unified Tool Bar and Bottom Bar, and refactored various bits of the API based on the great feedback I’ve received so far. The API is still fluid, so don’t be surprised if your code requires minor tweaks with the latest version. Also, a few people have asked for runnable demo code, which you’ll now find under the demo directory in the Subversion repository.

What components are coming next? A preferences widget and Heads Up Display (HUD) are on the way. What widgets would you like to see?

35 Responses to “Mac Widgets for Java – 0.9.1”

  1. Rob Juurlink Says:

    Cool, I wrote some similar GUI components for an application I work on. (ITunes inspired tree, tool bar and bottom bar).

    Do these widgets degrade well in Windows to the Windows Look & Feel?

  2. Ken Says:

    Hi Rob,

    These widgets render almost identically on Windows – the only differences being fonts and spacing.

    -Ken

  3. Steve McLeod Says:

    Ken,

    Could you briefly explain your rationale for not making com.explodingpixels.macwidgets.SourceList extend JComponent? It makes it hard to use Mac Widgets with a GUI Designer. (I’m using IntelliJ’s one.)

    Regards

    Steve

  4. Ken Says:

    Hi Steve,

    The idea is to minimize the API and thus make using the component more obvious and simple.

    JButton for example, has hundreds of methods. With each level of inheritance, the complexity multiplies, and it becomes harder and harder to use the component.

    Massive inheritance trees result in bloat, and many times, in methods being inherited that don’t make sense. For example, what does it mean for a JButton to auto scroll? It inherits the auto scroll property from JComponent, but this property doesn’t make sense for the JButton component.

    Frameworks like Cocoa suggest using aggregation over inheritance, as it reduces the overall surface area and helps ensure that components don’t contain unnecessary baggage. I’ve tried to be true to this approach by explicitly authoring the API that my components expose, thereby making it easier (hopefully) to use them.

    I’ve really come to like this pattern – hopefully others will to. I would, of course, like my library to work well with IntelliJ’s UI builder and other UI builders. I’ll email the developers at JetBrains to get their take on the issue.

    -Ken

  5. ranjith Says:

    Hi, Ken.
    Is the toolbar really unified under os x 10.5 java 1.6?
    I compiled the source from subversion, and I get the gray “non-unified” toolbar.

  6. Ken Says:

    Hi Ranjith,

    There’s an Apple bug reported against this – hopefully it will be fixed soon. If its not fixed in the next release of Java for the Mac, I’ll look into adding some temporary work-around code that manually paints the gradient.

    -Ken

  7. Mario Yohanes Says:

    Hi…

    I tried using your API version 0.9.0 and seems like still using SwingUtilities2 class, and I can’t run even your demo code.
    I used Eclipse with forbidden package import compiled as error.

    Does SwingUtilities2 has different package on JDK 1.6? Compiler error message said that no class definition for this class… It runs well on JDK 1.5…

    thanks for nice API… hope to see more cool widgets soon…

  8. Oren Says:

    I am having problems with running the demo with WinXP java1.6.0_10-beta. Any ideas?

    Exception in thread “AWT-EventQueue-0” java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:999)
    at java.awt.image.BufferedImage.(BufferedImage.java:321)
    at com.explodingpixels.macwidgets.plaf.UnifiedToolbarButtonUI.paintIcon(UnifiedToolbarButtonUI.java:47)
    at javax.swing.plaf.basic.BasicButtonUI.paint(BasicButtonUI.java:191)
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
    at javax.swing.JComponent.paintComponent(JComponent.java:763)
    at javax.swing.JComponent.paint(JComponent.java:1027)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5122)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:277)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1213)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5070)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4880)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:799)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
    at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
    at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:284)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

  9. Ken Says:

    Hi Mario,

    I replaced the use of SwingUtilities2 with BasicGraphicUtils (a public class) in version 0.9.1.

    -Ken

  10. Ken Says:

    Hi Oren,

    It looks like the image your supplying to the button isn’t getting loaded. See what happens when you use plain JButton. If your still having problems, you can submit an issue here.

    -Ken

  11. Mikael Grev Says:

    Hello Ken,

    Great work!

    Which license will/are you using?

    Cheers,
    Mikael Grev

  12. Ken Says:

    Thanks Mikael! I’m using the “friendly” LGPL.

    -Ken


  13. Hi Ken,

    I see your rationale about favoring delegation over inheritance.
    But you are not coding for Cocoa, you are coding for Swing.

    If you kept to the to the Swing design, i.e. MVC+UI-Delegate, lots more people could pick up your code, and for example, add the missing graceful degradation if a component is used on a non-Mac OS X platform.

    Other than that, your components look just awesome. 8)

  14. Ken Says:

    Hi Werner,

    I see componentized design as independent of the medium in which it is authored. It is more of a philosophy and style than anything else. Subscribing to a componentized design doesn’t preclude using model-view-controller and UI delegation – it just better hides the UI delegation from the developer.

    Another nice benefit of this design strategy is that it is easy to change the underlying implementation of the visual portion of the component.

    For example, my SourceList.getComponent() currently returns a JTree wrapped in JScrollPane, but I could easily change that to return a JXTree wrapped in a JScrollPane or some other tree-like implementation without affecting downstream developer. This is an explicit prevention of dependency. The goal is to expose only the details that the developer cares about. Finding out exactly what those needs are is an iterative process.

    Thanks for the engaging commentary.

    -Ken


  15. Hi Ken,

    Just let me put some more weight on the advantages of adhering to a well-known and widely used API:

    In essence, if your library adhered to the design principles of the API that my application already uses, it would have just ‘clicked into’ my existing code. And – one day in the future, if someone comes up with something either better looking -, it could be just as easily replaced.

    The different design approach of the Mac Widgets SourceList requires me to spend time to figure out, how I can integrate it with my existing code which is already in place for JTree and TreeModel.

    Now, I am pondering whether the design benefits of Mac Widgets justifies this extra amount of work…

    I know, I am always a little bit engaging. ;)
    I am just trying to tell you, why some people might be reluctant to use your library, although it is very well designed, both in terms of its visuals, and of its architecture.

  16. Ken Says:

    Hi Werner,

    Great points. I wonder if it would make sense to introduce a public UI delegate that could be used independently of the actual SourceList component. My SourceList would then package the entire component, as it does now, but the UI delegate would be available externally.

    This would be the best of both worlds. The one downside of course is that I would be fostering the incorrect usage of a Source List by providing a separately available delegate. I think this could be a fair compromise, though, helping to ease adoption.


  17. Your work is impressive, although I recommend that missing images result in a “not found” icon rather than taking down the entire rendering pipeline. Otherwise you’ll be forcing people to write a lot of defensive boilerplate code.

    A Scope Bar might be interesting, but it’s a ton of work.

    I was going to write “very impressive”, but then I saw SwingX and Forms :P That might cause some dependency issues since some LAF’s provide custom rendering code to SwingX components.
    .

  18. Ken Says:

    Hi Jan,

    I’m currently removing the dependency on SwingX, as I was using very little of their API. I probably won’t be removing the dependency on Forms, as it very useful and a small library.

    Which icons are causing issues? All of the production code (code not in the demo area) should work across platforms. If you’re having issues please email me directly ( kenneth.orr@gmail.com ) or file an issue ( http://code.google.com/p/macwidgets/issues/list ).

    -Ken

  19. Steve McLeod Says:

    Nice to hear you are removing the SwingX dependency. It’s adding 1.4 MB to my otherwise lean, mean consumer application.

  20. Zeljko Says:

    Few questions:
    – Is there a way to get selected item in SourceList ?
    – Is there a way to add JTextField in SourceListControlBar ?
    – Under Windows LAF there is a border around the button in ControlBar, how to remove it ?
    – It would be useful if there is getComponent() for ControlBar so it can be added to some other component.


    Zeljko

  21. Ken Says:

    Hi Zeljko,

    Is there a way to get the selected item in the SourceList?
    Yes. Use SourceList.getSelectedItem.

    Is there a way to add a JTextField to the SourceListControlBar?
    No. I’ve not seen a Source List button bar contain text fields before, so I don’t currently allow that. Let me know if you have a good use case for this.

    Why is there a border around the SourceListControlBar buttons on Windows?
    I’m not sure – can you send me a screen shot ( kenneth.orr@gmail.com )?

    Can you add a SourceListControlBar.getComponent method?
    Yes. I’ve updated SourceListControl bar and you can get the change from the subversion repository.

    -Ken

  22. ijabz Says:

    Although its not mentioned the demos are actaully included in the binary distribtion. But would be clearer if they were in their own package (e.g com.explodingpixels.macwidgets.test) rather than lumped directly into the com.explodingpixels.macwidgets package.

  23. ijabz Says:

    Great components but not convinced about favoring delegation over inheritance. I might be missing the point here but one problem I have is that your components are Mac Only, they wouldn’t look right in a Windows Application, but the widget concept is appropriate to both.

    For example both Windows and mac (and Linux) applications have a bottom bar. Im currently using JXStatusBar (from Swingx) to implement this if I implement your bottom bar I would need to start adding if(Aqua) conditions and use JXstatusbar for Windows and BottomBar for OSX.

  24. Ken Says:

    Hi ijabz,

    The demo code is included in the regular distribution, but should probably be its own jar file. The demos, tests and source all live in their own trunks like this:

    demo
        com.explodingpixels
    source
        com.explodingpixels
    test
        com.explodingpixels

    I prefer this mechanism for grouping as it doesn’t force me to introduce artificial packages. If you had a demo package under source, would you put all the demos in it, or only the ones at that level. In my experience, you’d end up with a scattered mess like this:

    source
        com.explodingpixels,macwidgets,demo
        com.explodingpixels,plaf,demo
        com.explodingpixels.widgets.demo

    -Ken

  25. Ken Says:

    Hi ijabz,

    Encapsulating the widgets into components doesn’t preclude giving them unique looks across platforms. The component could simply install the appropriate rendering delegate. This insulates the developer from implementation details.

    I have thus far decided to render these widgets the same across all platforms. Both Safari and iTunes are available for Windows, and they render almost identically to their Mac counterparts, so I think this approach is worthwhile. Many of the widgets have the Apple Human Interface Guidelines incorporated into them (like SourceList) and there aren’t really counterpart widgets on other platforms.

    -Ken

  26. ijabz Says:

    Personally I think Apples decision to make iTunes and Safari look MacLike on Windows is either a marketing decision to encourage a switch over to Macs, or is due to lack of dev effort/expertise on Windows.

    Your solution does offer one advantage I can develop on Windows and get a rough idea of wht it will look like on OSX before I deploy which is useful. Maybe your components could be used on Windows in Production with a different UI delegate, but coding one is beyond the realms of my expertise so I’ll go with my alternative for now, thanks.

  27. ijabz Says:

    The unified Toolbar uses this TriPart Component to layout the toolbar icons. But looking at the HIG and iTunes it is not clear to me that it really is always comprised of only seperate elements or less. Instead of using Forms you could use GroupLayout instead, I find it do pretty much anything

  28. Ken Says:

    Hi ijabz,

    GroupLayout is an implementation detail – that is, TriAreaComponent component could use that as the internal layout mechanism, though it currently uses FormLayout.

    The purpose of TriAreaComponent is to abstract away the complexities of dealing with layouts. You simply create a TriAreaComponent and call one of it’s three methods:

    addComponentToLeft
    addComponentToCenter
    addComponentToRight

    This is a more packaged solution than creating a JPanel and a GroupLayout with the right parameters each time you want to create a “tri-area” style component.

    -Ken

  29. ijabz Says:

    Yes I understand that, sorry there was a typo in my original post but the point I was trying to make was that not sure a Tri Area Model accurately reflects how the toolbar works. iTunes 8 has 5 different grouping of elements, it is not clear the correct way to model this using your TriAreaComponent. Is ‘tri-area’ style a known Apple HIG Concept ?

  30. Ken Says:

    Hi ijabz,

    I’m not sure exactly what you mean about iTunes 8 and five separate areas. The main purpose of TriAreaComponent is to offer a way to add to the left center and middle of component. iTunes 8 toolbar area is split up like this, with two sets of components on the left and two sets of components on the right and a component in the center.

    As far as I know, the tri-area style is not explicitly called out in the Apple HIG.

    -Ken


  31. […] behind the Mac Widgets for Java project, also announcing the availability of the source code and release 0.9.1 that features the unified tool bar and bottom bar components. And Brendon Chase has a short […]

  32. jamesthornton Says:

    Hi,

    I am running Mac OSX 10.5 and developing using Netbeans 6.5 and i have exactly the same problem as was mentioned in september:

    “ranjith Says:

    September 14, 2008 at 7:56 pm
    Hi, Ken.
    Is the toolbar really unified under os x 10.5 java 1.6?
    I compiled the source from subversion, and I get the gray “non-unified” toolbar.”

    I just wanted to know whether there have been any more developments or fixes on this bug?

    Thanks, James.

  33. Ken Says:

    Hi James,

    The issue you mention was fixed on December 3, 2008, so it didn’t make it into the 0.9.3 release. You can either check out the sources from Subversion, wait for the 0.9.4 release, or I can send you the latest jar file.

    -Ken


  34. […] have asked me about quite a bit about on this blog (you’ll find a few of my responses here, here and […]

  35. Marko Says:

    Where is GUI component for Netbenas
    http://java-mac-toolbar.webs.com/

    Totally free


Leave a reply to Rob Juurlink Cancel reply