// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.actions;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.util.List;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.gui.ExtendedDialog;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.gui.widgets.JosmComboBox;
import org.openstreetmap.josm.tools.GBC;
import org.openstreetmap.josm.tools.Shortcut;
import org.openstreetmap.josm.tools.Utils;
/**
* Abstract superclass of different "Merge" actions.
* @since 1890
*/
public abstract class AbstractMergeAction extends JosmAction {
/**
* the list cell renderer used to render layer list entries
*/
public static class LayerListCellRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Layer layer = (Layer) value;
JLabel label = (JLabel) super.getListCellRendererComponent(list, layer.getName(), index, isSelected, cellHasFocus);
label.setIcon(layer.getIcon());
label.setToolTipText(layer.getToolTipText());
return label;
}
}
/**
* Constructs a new {@code AbstractMergeAction}.
* @param name the action's text as displayed on the menu (if it is added to a menu)
* @param iconName the filename of the icon to use
* @param tooltip a longer description of the action that will be displayed in the tooltip. Please note
* that html is not supported for menu actions on some platforms.
* @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
* do want a shortcut, remember you can always register it with group=none, so you
* won't be assigned a shortcut unless the user configures one. If you pass null here,
* the user CANNOT configure a shortcut for your action.
* @param register register this action for the toolbar preferences?
*/
public AbstractMergeAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean register) {
super(name, iconName, tooltip, shortcut, register);
}
/**
* Constructs a new {@code AbstractMergeAction}.
* @param name the action's text as displayed on the menu (if it is added to a menu)
* @param iconName the filename of the icon to use
* @param tooltip a longer description of the action that will be displayed in the tooltip. Please note
* that html is not supported for menu actions on some platforms.
* @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
* do want a shortcut, remember you can always register it with group=none, so you
* won't be assigned a shortcut unless the user configures one. If you pass null here,
* the user CANNOT configure a shortcut for your action.
* @param register register this action for the toolbar preferences?
* @param toolbar identifier for the toolbar preferences. The iconName is used, if this parameter is null
* @param installAdapters false, if you don't want to install layer changed and selection changed adapters
*/
public AbstractMergeAction(String name, String iconName, String tooltip, Shortcut shortcut,
boolean register, String toolbar, boolean installAdapters) {
super(name, iconName, tooltip, shortcut, register, toolbar, installAdapters);
}
/**
* Ask user to choose the target layer.
* @param targetLayers list of candidate target layers.
* @return the chosen layer
*/
protected static Layer askTargetLayer(List<Layer> targetLayers) {
return askTargetLayer(targetLayers.toArray(new Layer[targetLayers.size()]),
tr("Please select the target layer."),
tr("Select target layer"),
tr("Merge"), "dialogs/mergedown");
}
/**
* Asks a target layer.
* @param <T> type of layer
* @param targetLayers array of proposed target layers
* @param label label displayed in dialog
* @param title title of dialog
* @param buttonText text of button used to select target layer
* @param buttonIcon icon name of button used to select target layer
* @return choosen target layer
*/
@SuppressWarnings("unchecked")
public static <T extends Layer> T askTargetLayer(T[] targetLayers, String label, String title, String buttonText, String buttonIcon) {
JosmComboBox<T> layerList = new JosmComboBox<>(targetLayers);
layerList.setRenderer(new LayerListCellRenderer());
layerList.setSelectedIndex(0);
JPanel pnl = new JPanel(new GridBagLayout());
pnl.add(new JLabel(label), GBC.eol());
pnl.add(layerList, GBC.eol());
if (GraphicsEnvironment.isHeadless()) {
// return first layer in headless mode, for unit tests
return targetLayers[0];
}
ExtendedDialog ed = new ExtendedDialog(Main.parent, title, new String[] {buttonText, tr("Cancel")});
ed.setButtonIcons(new String[] {buttonIcon, "cancel"});
ed.setContent(pnl);
ed.showDialog();
if (ed.getValue() != 1) {
return null;
}
return (T) layerList.getSelectedItem();
}
/**
* Warns user when there no layers the source layer could be merged to.
* @param sourceLayer source layer
*/
protected void warnNoTargetLayersForSourceLayer(Layer sourceLayer) {
String message = tr("<html>There are no layers the source layer<br>''{0}''<br>could be merged to.</html>",
Utils.escapeReservedCharactersHTML(sourceLayer.getName()));
if (!GraphicsEnvironment.isHeadless()) {
JOptionPane.showMessageDialog(Main.parent, message, tr("No target layers"), JOptionPane.WARNING_MESSAGE);
}
}
}