Enhanced ribbon application menu in Flamingo 4.2
October 22nd, 2009 | 5 Comments »Flamingo component suite provides a pure Swing implementation of Office 2007 ribbon component, and the latest 4.2dev drop of the core library has enhanced the support for ribbon application menu to provide default content of the secondary menu panel.
The application menu button is a big round button in the top left corner of the ribbon:

It is not a direct replacement for the usual application menu bar, but rather a place to hold actions that (as a general rule) do not affect the visual content of the document – such as saving, printing, sharing etc. When the application menu button is clicked, it shows a panel with two levels of actions:
- Primary action
- Secondary actions for the selected primary action
For example, a primary “Print” action will have a number of secondary actions to print the document as is, print from a dialog with all the options or open the print preview. In order to specify secondary actions, use the RibbonApplicationMenuEntryPrimary.addSecondaryMenuGroup API:
RibbonApplicationMenuEntryPrimary amEntryPrint = new RibbonApplicationMenuEntryPrimary( new document_print(), "Print", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Invoked printing document"); } }, CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION); amEntryPrint.setActionKeyTip("P"); amEntryPrint.setPopupKeyTip("W"); RibbonApplicationMenuEntrySecondary amEntryPrintSelect = new RibbonApplicationMenuEntrySecondary( new printer(), "Print", null, CommandButtonKind.ACTION_ONLY); amEntryPrintSelect .setDescriptionText("Select a printer, number of copies and other printing options before printing"); amEntryPrintSelect.setActionKeyTip("P"); RibbonApplicationMenuEntrySecondary amEntryPrintDefault = new RibbonApplicationMenuEntrySecondary( new document_print(), "Quick Print", null, CommandButtonKind.ACTION_ONLY); amEntryPrintDefault .setDescriptionText("Send the document directly to the default printer without making changes"); amEntryPrintDefault.setActionKeyTip("Q"); RibbonApplicationMenuEntrySecondary amEntryPrintPreview = new RibbonApplicationMenuEntrySecondary( new document_print_preview(), "Print Preview", null, CommandButtonKind.ACTION_ONLY); amEntryPrintPreview .setDescriptionText("Preview and make changes to the pages before printing"); amEntryPrintPreview.setActionKeyTip("V"); amEntryPrint.addSecondaryMenuGroup("Preview and print the document", amEntryPrintSelect, amEntryPrintDefault, amEntryPrintPreview);
At runtime when the user moves the mouse over the “Print” entry in the left panel, the matching secondary entries are shown on the right:

While most of the primary entries have a predefined (static) list of secondary entries, some require dynamic content. For example, the “Open” entry shows the list of recently open documents. In order to associate dynamic secondary content, use the RibbonApplicationMenuEntryPrimary.setRolloverCallback API:
RibbonApplicationMenuEntryPrimary amEntryOpen = new RibbonApplicationMenuEntryPrimary( new document_open(), "Open", new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Invoked opening document"); } }, CommandButtonKind.ACTION_ONLY); amEntryOpen .setRolloverCallback(new RibbonApplicationMenuEntryPrimary.PrimaryRolloverCallback() { @Override public void menuEntryActivated(JPanel targetPanel) { targetPanel.removeAll(); JCommandButtonPanel openHistoryPanel = new JCommandButtonPanel( CommandButtonDisplayState.MEDIUM); String groupName = "Recent Documents"; openHistoryPanel.addButtonGroup(groupName); for (int i = 0; i < 5; i++) { JCommandButton historyButton = new JCommandButton(i + " " + "document" + i + ".html", new text_html()); historyButton .setHorizontalAlignment(SwingUtilities.LEFT); openHistoryPanel .addButtonToLastGroup(historyButton); } openHistoryPanel.setMaxButtonColumns(1); targetPanel.setLayout(new BorderLayout()); targetPanel.add(openHistoryPanel, BorderLayout.CENTER); } }); amEntryOpen.setActionKeyTip("O");
Here, the application code is responsible for clearing and populating the contents of the secondary panel. At runtime when the user moves the mouse over the “Open” entry in the left panel, the application callback is invoked to populate the secondary panel:

The latest 4.2dev drop of Flamingo core library also allows the application code to specify the default content of the secondary panel. This is done with the new RibbonApplicationMenu.setDefaultCallback API. When set, it will be called when the ribbon application menu is shown, and when the currently active (under mouse) primary entry has neither secondary entries, nor rollover callback. In Office 2007 the default content of the secondary panel is the list of recently opened documents, but this API allows you to provide a custom implementation if necessary:
applicationMenu
.setDefaultCallback(new RibbonApplicationMenuEntryPrimary.PrimaryRolloverCallback() {
@Override
public void menuEntryActivated(JPanel targetPanel) {
targetPanel.removeAll();
JCommandButtonPanel openHistoryPanel = new JCommandButtonPanel(
CommandButtonDisplayState.MEDIUM);
String groupName = "Default Documents";
openHistoryPanel.addButtonGroup(groupName);
for (int i = 0; i < 5; i++) {
JCommandButton historyButton = new JCommandButton(i
+ " " + "default" + i + ".html",
new text_html());
historyButton
.setHorizontalAlignment(SwingUtilities.LEFT);
openHistoryPanel
.addButtonToLastGroup(historyButton);
}
openHistoryPanel.setMaxButtonColumns(1);
targetPanel.setLayout(new BorderLayout());
targetPanel.add(openHistoryPanel, BorderLayout.CENTER);
}
});When the default callback is invoked at runtime (under one of the two scenarios mentioned above), it populates the secondary panel:

If you want to see the enhanced application menu button in action, run the following WebStart demo:
The demo above works for the core look-and-feels. If you want to see this functionality under Substance, run the following WebStart demo:
If you want to test the new functionality in your applications, you would need the following (the last two only for applications running under Substance look-and-feel):
- The latest 4.2dev drop of Flamingo (code-named Hiolair)
- The latest 6.0dev drop of Substance (code-named Sonoma)
- The latest 6.0dev drop of Substance Flamingo plugin
Related posts:
- Flamingo ribbon component: application menu button and taskbar I’ve been relatively quiet on this blog for the last couple of weeks, but i...
- Flamingo ribbon component: enhancing the application menu button and popups Following the extremely valuable feedback on the previous entry that introduced the application menu button...
- Window / dock icon for ribbon frame in Flamingo 5.0 The application menu button in the ribbon component from Flamingo component suite is a big...
- Flamingo ribbon component: small buttons in ribbon galleries As mentioned in the JavaOne presentation on the Flamingo ribbon component, there are a few...
Hello Kirill,
I’m reading your posts since a long time, and since some weeks I have the opportunity to use and derive your components..
I like your job but something make me trouble : Why are you using “CallBack” instead of models for many of your components ?
Before having to reuse your components I have writed two customs components from scratch and obviously I have read a little doc and It seems that a “good” (for a Sun point of view [1]) component will have a Model, a Component and one or many UiDelegate but I think that you prefer “CallbBack”s instead of “old” models.
Thanks for your great work and your knowledges sharing
[1] http://today.java.net/pub/a/today/2007/02/22/how-to-write-custom-swing-component.html
Gervais,
Not sure that i follow your reasoning. RibbonApplicationMenu and RibbonApplicationMenuEntryPrimary are models – they don’t even extend the Component / JComponent. The components themselves have static behavior and dynamic behavior. The callbacks are used to provide the dynamic model behavior – and the UI delegates are calling the matching model APIs to populate the content dynamically at runtime.
What is your approach to allowing the applications to populate the list of recently open files when the application menu is showing?
Thanks
Kirill (incidentally, i wrote that article and i don’t work for Sun)
[...] Grouchnikov clearly had Flamingo on his mind this week, with two blog posts discussing how he has enhanced the ribbon application menu in Flamingo 4.2, and improvements to the command buttons in Flamingo to support buttons with no text and/or [...]
Kirill,
I’m sorry, I feel you a little angry but my questions isn’t a accusation or any other bad things. It’s just a question from a rookie to a more experienced (and respected) developper.
I have only used your BreadCrumbBar (v 2.0) and constated that there was no “xxxModel” classes but only “CallBack”s.
I have another approach to populate the list, but she isn’t so “sexy” a lighter than your “CallBacks”.
A second time, I want to present all my respect and please don’t considers my questions as an accusatiuon about your work.
Gervais,
That’s one of the problems with written communication – i was just asking you to clarify your question in order to better understand your reservations about the callbacks.
Breadcrumb bar component is not all my doing – it was contributed a few years ago by a third party. While i have refactored some of the API and most of the UI delegates, some of the APIs remained the same. It’s a very dynamic component, and as such is driven entirely by application callbacks. It may indeed be refactored to fit the MVC paradigm a little better, but i’m afraid it will be some time before i get to it.
You’re more than welcome to share your thoughts / code on the project “users” mailing list to see if the next major release is a good fit for the API facelift.
Thanks
Kirill