/*
* WPCleaner: A tool to help on Wikipedia maintenance tasks.
* Copyright (C) 2013 Nicolas Vervelle
*
* See README.txt file for licensing information.
*/
package org.wikipediacleaner.gui.swing.menu;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionListener;
import java.awt.font.TextAttribute;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import org.wikipediacleaner.api.data.Page;
import org.wikipediacleaner.gui.swing.basic.Utilities;
import org.wikipediacleaner.utils.Configuration;
import org.wikipediacleaner.utils.ConfigurationValueInteger;
/**
* A helper class to manage contextual menu.
*/
public abstract class AbstractMenuCreator {
// ==========================================================================
// Managing menu structure
// ==========================================================================
/**
* Add a separator to a menu if useful.
*
* @param menu Menu.
* @return Number of items added.
*/
public int addSeparator(JMenu menu) {
if ((menu == null) || (menu.getMenuComponentCount() == 0)) {
return 0;
}
Component item = menu.getMenuComponent(menu.getMenuComponentCount() - 1);
if (!(item instanceof JMenuItem)) {
return 0;
}
menu.add(new JSeparator());
return 1;
}
/**
* Add a separator to a menu if useful.
*
* @param menu Menu.
* @return Number of items added.
*/
public int addSeparator(JPopupMenu menu) {
if ((menu == null) || (menu.getComponentCount() == 0)) {
return 0;
}
Component item = menu.getComponent(menu.getComponentCount() - 1);
if (!(item instanceof JMenuItem)) {
return 0;
}
menu.add(new JSeparator());
return 1;
}
/**
* Add a disabled text to a menu.
*
* @param menu Menu.
* @param text Text of the item.
* @return Number of items added.
*/
public int addDisabledText(JMenu menu, String text) {
if ((menu == null) || (text == null) || (text.length() == 0)) {
return 0;
}
JMenuItem menuItem = new JMenuItem(text);
menuItem.setEnabled(false);
menu.add(menuItem);
return 1;
}
/**
* Add a disabled text to a menu.
*
* @param menu Menu.
* @param text Text of the item.
* @return Number of items added.
*/
public int addDisabledText(JPopupMenu menu, String text) {
if ((menu == null) || (text == null) || (text.length() == 0)) {
return 0;
}
JMenuItem menuItem = new JMenuItem(text);
menuItem.setEnabled(false);
menu.add(menuItem);
return 1;
}
/**
* Add an item to a menu.
*
* @param menu Menu.
* @param page Page.
* @param title Element title (if null, the page title will be used).
* @param asIs True if the message should be used as is (no mnemonic).
* @param action Action.
* @return Number of items added.
*/
public int addItem(
JMenu menu, Page page, String title, boolean asIs,
ActionListener action) {
return addItem(menu, page, title, asIs, action, null);
}
/**
* Add an item to a menu.
*
* @param menu Menu.
* @param page Page.
* @param title Element title (if null, the page title will be used).
* @param asIs True if the message should be used as is (no mnemonic).
* @param action Action.
* @param accelerator Accelerator.
* @return Number of items added.
*/
public int addItem(
JMenu menu, Page page, String title, boolean asIs,
ActionListener action, KeyStroke accelerator) {
if (menu == null) {
return 0;
}
if ((title == null) && ((page == null) || (page.getTitle() == null))) {
return 0;
}
JMenuItem menuItem = Utilities.createJMenuItem(title != null ? title : page.getTitle(), asIs);
if (page != null) {
updateFont(menuItem, page);
}
if (action != null) {
menuItem.addActionListener(action);
}
if (accelerator != null) {
menuItem.setAccelerator(accelerator);
}
menu.add(menuItem);
return 1;
}
/**
* Add an item to a menu.
*
* @param menu Menu.
* @param page Page.
* @param title Element title (if null, the page title will be used).
* @param asIs True if the message should be used as is (no mnemonic).
* @param action Action.
* @return Number of items added.
*/
public int addItem(
JPopupMenu menu, Page page, String title, boolean asIs,
ActionListener action) {
return addItem(menu, page, title, asIs, action, null);
}
/**
* Add an item to a menu.
*
* @param menu Menu.
* @param page Page.
* @param title Element title (if null, the page title will be used).
* @param asIs True if the message should be used as is (no mnemonic).
* @param action Action.
* @param accelerator Accelerator.
* @return Number of items added.
*/
public int addItem(
JPopupMenu menu, Page page, String title, boolean asIs,
ActionListener action, KeyStroke accelerator) {
if (menu == null) {
return 0;
}
if ((title == null) && ((page == null) || (page.getTitle() == null))) {
return 0;
}
JMenuItem menuItem = Utilities.createJMenuItem(title != null ? title : page.getTitle(), asIs);
if (page != null) {
updateFont(menuItem, page);
}
if (action != null) {
menuItem.addActionListener(action);
}
if (accelerator != null) {
menuItem.setAccelerator(accelerator);
}
menu.add(menuItem);
return 1;
}
/**
* Add a submenu to a menu.
* If the submenu contains to much elements, it is split into several submenus.
*
* @param menu Menu.
* @param submenu Submenu.
* @param begin Number of items kept at the beginning.
* @param end Number of items kept at the end.
*/
public void addSubmenu(JMenu menu, JMenu submenu, int begin, int end) {
addSubmenu(menu.getPopupMenu(), submenu, begin, end);
}
/**
* Add a submenu to a menu.
* If the submenu contains to much elements, it is split into several submenus.
*
* @param menu Menu.
* @param submenu Submenu.
* @param begin Number of items kept at the beginning.
* @param end Number of items kept at the end.
*/
public void addSubmenu(JPopupMenu menu, JMenu submenu, int begin, int end) {
Configuration config = Configuration.getConfiguration();
final int maxElements = Math.max(
config.getInt(null, ConfigurationValueInteger.MENU_SIZE),
begin + end + 2);
if (submenu.getMenuComponentCount() > maxElements) {
List<JMenu> menuList = new ArrayList<JMenu>();
while (submenu.getMenuComponentCount() > begin + end + 1) {
int count = Math.min(maxElements, submenu.getMenuComponentCount() - begin - end);
JMenu newMenu = new JMenu(submenu.getItem(begin).getText() + "...");
for (int i = 0; i < count; i++) {
JMenuItem item = submenu.getItem(begin);
submenu.remove(begin);
if (item != null) {
newMenu.add(item);
} else {
addSeparator(newMenu);
}
}
menuList.add(newMenu);
}
for (int i = 0; i < menuList.size(); i++) {
submenu.add(menuList.get(i), begin + i);
}
addSubmenu(menu, submenu, begin, end);
} else {
menu.add(submenu);
}
}
/**
* Add submenus to a menu.
*
* @param menu Menu.
* @param items Submenus.
*/
public void addSubmenus(JPopupMenu menu, List<JMenuItem> items) {
Configuration config = Configuration.getConfiguration();
final int maxElements = Math.max(config.getInt(null, ConfigurationValueInteger.MENU_SIZE), 10);
if (items.size() <= maxElements) {
for (JMenuItem item : items) {
menu.add(item);
}
return;
}
int i = 0;
while (i < items.size()) {
JMenu currentMenu = new JMenu(items.get(i).getText());
menu.add(currentMenu);
while ((i < items.size()) && (currentMenu.getItemCount() < maxElements)) {
currentMenu.add(items.get(i));
i++;
}
}
}
// ==========================================================================
// Rendering menu items
// ==========================================================================
/**
* Attributes for rendering menu items for disambiguation pages.
*/
final private static Map<TextAttribute, Color> disambiguationAttributes = new HashMap<TextAttribute, Color>();
/**
* Attributes for rendering menu items for missing pages.
*/
final private static Map<TextAttribute, Boolean> missingAttributes = new HashMap<TextAttribute, Boolean>();
/**
* Attributes for rendering menu items for redirect pages.
*/
final private static Map<TextAttribute, Float> redirectAttributes = new HashMap<TextAttribute, Float>();
static {
disambiguationAttributes.put(TextAttribute.FOREGROUND, Color.RED);
missingAttributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
redirectAttributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
}
/**
* Update menuItem style depending on the page attributes.
*
* @param menuItem Menu item.
* @param page Page.
*/
protected void updateFont(JMenuItem menuItem, Page page) {
if ((menuItem == null) || (page == null)) {
return;
}
if (page.isRedirect()) {
menuItem.setFont(menuItem.getFont().deriveFont(redirectAttributes));
}
if (Boolean.TRUE.equals(page.isDisambiguationPage())) {
menuItem.setFont(menuItem.getFont().deriveFont(disambiguationAttributes));
}
if (Boolean.FALSE.equals(page.isExisting())) {
menuItem.setFont(menuItem.getFont().deriveFont(missingAttributes));
}
}
}