001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.tagging.presets.items; 003 004import java.awt.GridBagLayout; 005import java.awt.event.MouseAdapter; 006import java.awt.event.MouseEvent; 007import java.util.ArrayList; 008import java.util.Arrays; 009import java.util.Collection; 010import java.util.List; 011 012import javax.swing.ImageIcon; 013import javax.swing.JLabel; 014import javax.swing.JPanel; 015import javax.swing.SwingConstants; 016 017import org.openstreetmap.josm.data.osm.OsmPrimitive; 018import org.openstreetmap.josm.data.osm.OsmUtils; 019import org.openstreetmap.josm.data.osm.Tag; 020import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetReader; 021import org.openstreetmap.josm.gui.widgets.QuadStateCheckBox; 022import org.openstreetmap.josm.tools.GBC; 023 024/** 025 * Checkbox type. 026 */ 027public class Check extends KeyedItem { 028 029 /** The localized version of {@link #text}. */ 030 public String locale_text; // NOSONAR 031 /** the value to set when checked (default is "yes") */ 032 public String value_on = OsmUtils.TRUE_VALUE; // NOSONAR 033 /** the value to set when unchecked (default is "no") */ 034 public String value_off = OsmUtils.FALSE_VALUE; // NOSONAR 035 /** whether the off value is disabled in the dialog, i.e., only unset or yes are provided */ 036 public boolean disable_off; // NOSONAR 037 /** "on" or "off" or unset (default is unset) */ 038 public String default_; // only used for tagless objects // NOSONAR 039 /** The location of icon file to display */ 040 public String icon; // NOSONAR 041 /** The size of displayed icon. If not set, default is 16px */ 042 public String icon_size; // NOSONAR 043 044 private QuadStateCheckBox check; 045 private QuadStateCheckBox.State initialState; 046 private Boolean def; 047 048 @Override 049 public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) { 050 051 // find out if our key is already used in the selection. 052 final Usage usage = determineBooleanUsage(sel, key); 053 final String oneValue = usage.values.isEmpty() ? null : usage.values.last(); 054 def = "on".equals(default_) ? Boolean.TRUE : "off".equals(default_) ? Boolean.FALSE : null; 055 056 if (locale_text == null) { 057 locale_text = getLocaleText(text, text_context, null); 058 } 059 060 if (usage.values.size() < 2 && (oneValue == null || value_on.equals(oneValue) || value_off.equals(oneValue))) { 061 if (def != null && !PROP_FILL_DEFAULT.get()) { 062 // default is set and filling default values feature is disabled - check if all primitives are untagged 063 for (OsmPrimitive s : sel) { 064 if (s.hasKeys()) { 065 def = null; 066 } 067 } 068 } 069 070 // all selected objects share the same value which is either true or false or unset, 071 // we can display a standard check box. 072 initialState = value_on.equals(oneValue) || Boolean.TRUE.equals(def) 073 ? QuadStateCheckBox.State.SELECTED 074 : value_off.equals(oneValue) || Boolean.FALSE.equals(def) 075 ? QuadStateCheckBox.State.NOT_SELECTED 076 : QuadStateCheckBox.State.UNSET; 077 078 } else { 079 def = null; 080 // the objects have different values, or one or more objects have something 081 // else than true/false. we display a quad-state check box 082 // in "partial" state. 083 initialState = QuadStateCheckBox.State.PARTIAL; 084 } 085 086 final List<QuadStateCheckBox.State> allowedStates = new ArrayList<>(4); 087 if (QuadStateCheckBox.State.PARTIAL == initialState) 088 allowedStates.add(QuadStateCheckBox.State.PARTIAL); 089 allowedStates.add(QuadStateCheckBox.State.SELECTED); 090 if (!disable_off || value_off.equals(oneValue)) 091 allowedStates.add(QuadStateCheckBox.State.NOT_SELECTED); 092 allowedStates.add(QuadStateCheckBox.State.UNSET); 093 check = new QuadStateCheckBox(icon == null ? locale_text : null, initialState, 094 allowedStates.toArray(new QuadStateCheckBox.State[0])); 095 check.setPropertyText(key); 096 check.setState(check.getState()); // to update the tooltip text 097 098 if (icon != null) { 099 JPanel checkPanel = new JPanel(new GridBagLayout()); 100 checkPanel.add(check, GBC.std()); 101 JLabel label = new JLabel(locale_text, getIcon(), SwingConstants.LEFT); 102 label.addMouseListener(new MouseAdapter() { 103 @Override 104 public void mousePressed(MouseEvent e) { 105 check.getMouseAdapter().mousePressed(e); 106 } 107 }); 108 checkPanel.add(label); 109 checkPanel.add(new JLabel(), GBC.eol().fill()); 110 p.add(checkPanel, GBC.eol()); // Do not fill, see #15104 111 } else { 112 p.add(check, GBC.eol()); // Do not fill, see #15104 113 } 114 return true; 115 } 116 117 @Override 118 public void addCommands(List<Tag> changedTags) { 119 // if the user hasn't changed anything, don't create a command. 120 if (def == null && check.getState() == initialState) return; 121 122 // otherwise change things according to the selected value. 123 changedTags.add(new Tag(key, 124 check.getState() == QuadStateCheckBox.State.SELECTED ? value_on : 125 check.getState() == QuadStateCheckBox.State.NOT_SELECTED ? value_off : 126 null)); 127 } 128 129 @Override 130 public MatchType getDefaultMatch() { 131 return MatchType.NONE; 132 } 133 134 /** 135 * Returns the entry icon, if any. 136 * @return the entry icon, or {@code null} 137 * @since 15437 138 */ 139 public ImageIcon getIcon() { 140 Integer size = parseInteger(icon_size); 141 return icon == null ? null : loadImageIcon(icon, TaggingPresetReader.getZipIcons(), size != null ? size : 16); 142 } 143 144 @Override 145 public Collection<String> getValues() { 146 return disable_off ? Arrays.asList(value_on) : Arrays.asList(value_on, value_off); 147 } 148 149 @Override 150 public String toString() { 151 return "Check [key=" + key + ", text=" + text + ", " 152 + (locale_text != null ? "locale_text=" + locale_text + ", " : "") 153 + (value_on != null ? "value_on=" + value_on + ", " : "") 154 + (value_off != null ? "value_off=" + value_off + ", " : "") 155 + "default_=" + default_ + ", " 156 + (check != null ? "check=" + check + ", " : "") 157 + (initialState != null ? "initialState=" + initialState 158 + ", " : "") + "def=" + def + ']'; 159 } 160}