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.gui.MainApplication; 022import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 023import org.openstreetmap.josm.gui.layer.Layer.LayerAction; 024import org.openstreetmap.josm.gui.layer.Layer.MultiLayerAction; 025import org.openstreetmap.josm.tools.ImageProvider; 026 027/** 028 * Action to show a dialog for picking a color. 029 * 030 * By calling this action, the user can choose a color to customize the painting 031 * of a certain {@link GpxLayer} or {@link org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer}. 032 */ 033public class CustomizeColor extends AbstractAction implements LayerAction, MultiLayerAction { 034 private final transient List<Layer> colorLayers; 035 036 /** 037 * Constructs a new {@code CustomizeColor} for a given list of layers. 038 * @param l list of layers 039 */ 040 public CustomizeColor(List<Layer> l) { 041 super(tr("Customize Color")); 042 new ImageProvider("colorchooser").getResource().attachImageIcon(this, true); 043 colorLayers = l.stream().filter(Objects::nonNull).filter(Layer::hasColor).collect(Collectors.toList()); 044 putValue("help", ht("/Action/LayerCustomizeColor")); 045 } 046 047 /** 048 * Constructs a new {@code CustomizeColor} for a single layer. 049 * @param l layer 050 */ 051 public CustomizeColor(Layer l) { 052 this(Collections.singletonList(l)); 053 } 054 055 @Override 056 public boolean supportLayers(List<Layer> layers) { 057 return layers.stream().allMatch(Layer::hasColor); 058 } 059 060 @Override 061 public Component createMenuComponent() { 062 return new JMenuItem(this); 063 } 064 065 @Override 066 public Action getMultiLayerAction(List<Layer> layers) { 067 return new CustomizeColor(layers); 068 } 069 070 @Override 071 public void actionPerformed(ActionEvent e) { 072 Color cl = colorLayers.stream().filter(Objects::nonNull).map(Layer::getColor).filter(Objects::nonNull).findAny().orElse(Color.GRAY); 073 JColorChooser c = new JColorChooser(cl); 074 Object[] options = {tr("OK"), tr("Cancel"), tr("Default")}; 075 int answer = JOptionPane.showOptionDialog( 076 MainApplication.getMainFrame(), 077 c, 078 tr("Choose a color"), 079 JOptionPane.OK_CANCEL_OPTION, 080 JOptionPane.PLAIN_MESSAGE, 081 null, 082 options, 083 options[0] 084 ); 085 switch (answer) { 086 case 0: 087 colorLayers.stream().forEach(l -> l.setColor(c.getColor())); 088 break; 089 case 1: 090 return; 091 case 2: 092 colorLayers.stream().forEach(l -> l.setColor(null)); 093 break; 094 } 095 // TODO: Make the layer dialog listen to property change events so that this is not needed any more. 096 LayerListDialog.getInstance().repaint(); 097 } 098}