001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.Color; 008import java.awt.Component; 009import java.awt.event.ActionEvent; 010import java.util.Collections; 011import java.util.List; 012import java.util.Objects; 013import java.util.stream.Collectors; 014 015import javax.swing.AbstractAction; 016import javax.swing.Action; 017import javax.swing.JColorChooser; 018import javax.swing.JMenuItem; 019import javax.swing.JOptionPane; 020 021import org.openstreetmap.josm.Main; 022import org.openstreetmap.josm.data.preferences.AbstractProperty; 023import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 024import org.openstreetmap.josm.gui.layer.Layer.LayerAction; 025import org.openstreetmap.josm.gui.layer.Layer.MultiLayerAction; 026import org.openstreetmap.josm.tools.CheckParameterUtil; 027import org.openstreetmap.josm.tools.ImageProvider; 028 029public class CustomizeColor extends AbstractAction implements LayerAction, MultiLayerAction { 030 private final transient List<AbstractProperty<Color>> colors; 031 032 /** 033 * Constructs a new {@code CustomizeColor} for a given list of layers. 034 * @param l list of layers 035 */ 036 public CustomizeColor(List<Layer> l) { 037 super(tr("Customize Color"), ImageProvider.get("colorchooser")); 038 colors = l.stream().map(Layer::getColorProperty).collect(Collectors.toList()); 039 CheckParameterUtil.ensureThat(colors.stream().allMatch(Objects::nonNull), "All layers must have colors."); 040 putValue("help", ht("/Action/LayerCustomizeColor")); 041 } 042 043 /** 044 * Constructs a new {@code CustomizeColor} for a single layer. 045 * @param l layer 046 */ 047 public CustomizeColor(Layer l) { 048 this(Collections.singletonList(l)); 049 } 050 051 @Override 052 public boolean supportLayers(List<Layer> layers) { 053 return layers.stream().allMatch(l -> l.getColorProperty() != null); 054 } 055 056 @Override 057 public Component createMenuComponent() { 058 return new JMenuItem(this); 059 } 060 061 @Override 062 public Action getMultiLayerAction(List<Layer> layers) { 063 return new CustomizeColor(layers); 064 } 065 066 @Override 067 public void actionPerformed(ActionEvent e) { 068 Color cl = colors.stream().map(AbstractProperty::get).filter(Objects::nonNull).findAny().orElse(Color.GRAY); 069 JColorChooser c = new JColorChooser(cl); 070 Object[] options = new Object[]{tr("OK"), tr("Cancel"), tr("Default")}; 071 int answer = JOptionPane.showOptionDialog( 072 Main.parent, 073 c, 074 tr("Choose a color"), 075 JOptionPane.OK_CANCEL_OPTION, 076 JOptionPane.PLAIN_MESSAGE, 077 null, 078 options, 079 options[0] 080 ); 081 switch (answer) { 082 case 0: 083 colors.stream().forEach(prop -> prop.put(c.getColor())); 084 break; 085 case 1: 086 return; 087 case 2: 088 colors.stream().forEach(prop -> prop.put(null)); 089 break; 090 } 091 // TODO: Make the layer dialog listen to property change events so that this is not needed any more. 092 LayerListDialog.getInstance().repaint(); 093 } 094}