Flamingo component suite began its life in January 2006 when Rick Jeliffe of Topologi has contacted me and proposed to open-source their own implementation of the breadcrumb bar component. In the years since i have hacked at different pieces of the breadcrumb bar implementation. As with any significant piece of code that you get to maintain and extend, it takes some time to find your way around the code, and this was no exception.

Piece by piece i cleaned the component API, refactored the code into the model and UI delegates and integrated the API with the command button panel. The last (almost) untouched piece was the painting of individual segments. It was rather cumbersome, and i finally got around to replacing it all with command buttons. This not only helped removing a lot of code that was implementing the same functionality available in command buttons, but also pointed out missing pieces that were added in the last few weeks to command buttons and command popup menus.

If you’re using the breadcrumb bar component in your application, you should not see any difference – except more polished look. If you’re using command buttons in your application, here are a couple of tips on how to use them to their fullest potential. First, a screenshot of a file explorer that uses the breadcrumb bar (under the Gemini skin from Substance look-and-feel):

https://flamingo.dev.java.net/release-info/5.0/breadcrumbbar.png

When the breadcrumb segment is inactive, its arrow points to the side. When the mouse is over the arrow icon, the arrow points downwards. Here is how the command button is configured:

button.setDisplayState(CommandButtonDisplayState.MEDIUM);
button.setPopupOrientationKind(CommandButtonPopupOrientationKind.SIDEWARD);
button.setHGapScaleFactor(0.75);
button.getPopupModel().addChangeListener(new ChangeListener() {
   @Override
   public void stateChanged(ChangeEvent e) {
      PopupButtonModel model = button.getPopupModel();
      boolean displayDownwards = model.isRollover()
            || model.isPopupShowing();
      CommandButtonPopupOrientationKind popupOrientationKind = displayDownwards ?
            CommandButtonPopupOrientationKind.DOWNWARD
            : CommandButtonPopupOrientationKind.SIDEWARD;
      button.setPopupOrientationKind(popupOrientationKind);
   }
});

First, we configure the button to be in MEDIUM display state (small icon and text right beside it), set the popup orientation kind to SIDEWARD and set the horizontal gap scale factor to 0.75 (to have smaller horizontal gap between the icon, text and arrow). Then, we add a ChangeListener to the button’s popup model. The listener checks to see if the mouse is over the popup area with PopupButtonModel.isRollover() or the popup is showing with PopupButtonModel.isPopupShowing(). Then we call JCommandButton.setPopupOrientationKind with DOWNWARD if either condition holds, or SIDEWARD otherwise. This is it – and using only published JCommandButton APIs.

If you use the breadcrumb bar in your application, try showing the popup menu and then move the mouse along the breadcrumb bar while the popup menu is showing. You will see that when you move the mouse over the popup area of another segment, the breadcrumb bar will automatically show the popup menu for that segment – without a need to click it. Here is the relevant code:

button.getPopupModel().addChangeListener(new ChangeListener() {
   boolean rollover = button.getPopupModel().isRollover();

   @Override
   public void stateChanged(ChangeEvent e) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            boolean isRollover = button.getPopupModel()
                  .isRollover();
            if (isRollover == rollover)
               return;

            if (isRollover) {
               // does any *other* button show popup?
               for (JCommandButton bcbButton : buttonStack) {
                  if (bcbButton == button)
                     continue;

                  if (bcbButton.getPopupModel().isPopupShowing()) {
                     // scroll to view
                     scrollerPanel.scrollToIfNecessary(button
                           .getBounds().x, button.getWidth());
                     // simulate click on the popup area
                     // of *this* button
                     button.doPopupClick();
                  }
               }
            }

            rollover = isRollover;
         }
      });
   }
});

What do we have here? Once again, we add a ChangeListener to the popup model of every segment. In the listener we are tracking changes to the rollover state. If we detect a change, and the new value is true, we go over all the buttons in the breadcrumb bar and try to locate a button that displays the popup menu (there can only be at most one at any time). If we found any – using PopupButtonModel.isPopupShowing() – it means that we need to show the popup menu for our button. We ask the scroller panel that wraps the breadcrumb bar to scroll our button so that it becomes full visible (more on this in the next blog entry) and then call JCommandButton.doPopupClick(). Internally this is handled as a regular mouse click on the popup area – dismissing the current popup menu, invoking the popup callback of our button to return the popup menu and displaying the popup menu aligned with our button.

In addition to being able to use the powerful published APIs of the command buttons, the breadcrumb bar now looks much better – both under core look-and-feels, and under the different Substance skins. The screenshot above shows the breadcrumb bar under Gemini skin that uses dark background for the header section. The breadcrumb bar gets all the right visuals since it is now implemented with command buttons which get all the right colors, and rollover animations.

If you want to take the new breadcrumb bar (with the same external APIs) for a spin, you will need the following:

Note that the last two are required if you’re running your application under one of Substance skins. You will need the 6.1dev drop of Substance Flamingo plugin – the latest 5.0dev drop of Flamingo core is incompatible with the 6.0 release of Substance Flamingo plugin – as mentioned before.

I’ve spend the last few days pushing a few pixels improving the alignment of ribbon band controls in the latest Flamingo 5.0dev. This is how it looked before:

https://flamingo.dev.java.net/release-info/5.0/ribbon-button-alignment-old.png

And this is how it looks now:

https://flamingo.dev.java.net/release-info/5.0/ribbon-button-alignment-new.png

Main improvements:

  • Equal amount of horizontal white space around the controls
  • Equal amount of vertical white space between the buttons
  • Aligning bottom edges of controls across columns

The change is in Flamingo 5.0dev only, so you can still use the final 6.0 releases of Substance core and Substance Flamingo plugin. There’s also a matching test case using the excellent FEST library. Thanks to Ivan for pointing this out and testing the fixes.

Release miscellania

April 14th, 2010

In addition to releasing Trident 1.2 and Substance 6.0, today i have released the following:

  • Laf-Plugin version 1.2 code named Landshark. This is used by Substance to find and load its plugins.
  • Laf-Widget version 5.0 code named Magnolia. This is used by Substance to add visual and behavioral features to specific component types.
  • Lightbeam version 1.1 code named Betelgeuse. This is used to analyze Substance performance and make sure there are no performance regressions.
  • Rainbow version 1.2 code named Blackstone. A small test application written with Alex Potochkin to test Substance, Flamingo and JXLayer.

An unfortunate omission is the Flamingo component suite. As much as i would have loved to be able to have Flamingo 5.0 join the release train today, it was not realistic given the time constraints. So, instead of delaying the releases of all the projects, i have decided to have Flamingo be developed in its own timeline. The final 6.0 release of Substance Flamingo is based on the latest 5.0dev daily drops of Flamingo core. As the work on Flamingo core continues, the interested applications will need to use daily builds of Substance and Substance Flamingo. My intent is to release Flamingo 5.0 together with Substance 6.1.

The command button component is a central building block for the Flamingo component suite. It aims to address the deficiencies of the core Swing button components, adding features expected by the modern applications. While the main goal of Flamingo is to provide a pure Java implementation of the Office 2007 ribbon container, the command buttons can certainly be used outside the ribbon.

Command buttons can be configured to have two separate areas – action and popup. This allows the application to use command buttons as drop-in replacement for Swing core buttons, as well as use them to create split and popup buttons. The JCommandButton.setPopupCallback API is used to dynamically create the popup menu content when the popup area is activated. The core org.pushingpixels.flamingo.common.popup.JCommandPopupMenu allows creating most commonly used popup menus. You can use its addMenuButton and addMenuSeparator to create simple menus:

https://flamingo.dev.java.net/release-info/5.0/button-popup-simple.png

or you can use a JCommandPopupMenu constructor that gets a JCommandButtonPanel instance to create a more complex popup menu with embedded scrollable command button panel:

https://flamingo.dev.java.net/release-info/5.0/button-popup-with-buttonpanel.png

If a popup menu hosts a large number of command menu buttons, it may overflow the vertical boundaries of the monitor, resulting in poor UI experience. Even though such scenarios usually indicate poor UI design (too many choices), sometimes it is a valid requirement. One such example is showing all files in the specific folder when the user clicks the popup area. To address such scenarios, you can use the new JCommandPopupMenu.setMaxVisibleMenuButtons(int) API.

Suppose you use this API with the value 10. If your popup menu contains ten items or less, it will be shown as it is today. However, if it contains more than ten items, the popup menu will show two scroller buttons, one before the first menu item, and another after the last menu item:

https://flamingo.dev.java.net/release-info/5.0/button-popup-scrollable-top.png

To scroll through the items, use the mouse wheel or move the mouse over the bottom scroller button. In the later case, there’s no need to click the mouse button – the scrolling will start automatically when the mouse is moved over the scroller button and will continue as long as the mouse stays there. Once you start scrolling, the top scroller button becomes enabled:

https://flamingo.dev.java.net/release-info/5.0/button-popup-scrollable-middle.png

When you reach the last menu button, the bottom scroller button becomes disabled:

https://flamingo.dev.java.net/release-info/5.0/button-popup-scrollable-bottom.png

To test the new functionality in your applications, you will need the following:

Note that the last two are required if you’re running your application under one of Substance skins – such as Office Blue 2007 used in all the screenshots in this entry.