001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.tagging.presets.items; 003 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.Collection; 007import java.util.List; 008 009import javax.swing.JPanel; 010 011import org.openstreetmap.josm.data.osm.OsmPrimitive; 012import org.openstreetmap.josm.data.osm.OsmUtils; 013import org.openstreetmap.josm.data.osm.Tag; 014import org.openstreetmap.josm.gui.widgets.QuadStateCheckBox; 015import org.openstreetmap.josm.tools.GBC; 016 017/** 018 * Checkbox type. 019 */ 020public class Check extends KeyedItem { 021 022 /** The localized version of {@link #text}. */ 023 public String locale_text; 024 /** the value to set when checked (default is "yes") */ 025 public String value_on = OsmUtils.trueval; 026 /** the value to set when unchecked (default is "no") */ 027 public String value_off = OsmUtils.falseval; 028 /** whether the off value is disabled in the dialog, i.e., only unset or yes are provided */ 029 public boolean disable_off; 030 /** "on" or "off" or unset (default is unset) */ 031 public String default_; // only used for tagless objects 032 033 private QuadStateCheckBox check; 034 private QuadStateCheckBox.State initialState; 035 private Boolean def; 036 037 @Override 038 public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) { 039 040 // find out if our key is already used in the selection. 041 final Usage usage = determineBooleanUsage(sel, key); 042 final String oneValue = usage.values.isEmpty() ? null : usage.values.last(); 043 def = "on".equals(default_) ? Boolean.TRUE : "off".equals(default_) ? Boolean.FALSE : null; 044 045 if (locale_text == null) { 046 locale_text = getLocaleText(text, text_context, null); 047 } 048 049 if (usage.values.size() < 2 && (oneValue == null || value_on.equals(oneValue) || value_off.equals(oneValue))) { 050 if (def != null && !PROP_FILL_DEFAULT.get()) { 051 // default is set and filling default values feature is disabled - check if all primitives are untagged 052 for (OsmPrimitive s : sel) { 053 if (s.hasKeys()) { 054 def = null; 055 } 056 } 057 } 058 059 // all selected objects share the same value which is either true or false or unset, 060 // we can display a standard check box. 061 initialState = value_on.equals(oneValue) || Boolean.TRUE.equals(def) 062 ? QuadStateCheckBox.State.SELECTED 063 : value_off.equals(oneValue) || Boolean.FALSE.equals(def) 064 ? QuadStateCheckBox.State.NOT_SELECTED 065 : QuadStateCheckBox.State.UNSET; 066 067 } else { 068 def = null; 069 // the objects have different values, or one or more objects have something 070 // else than true/false. we display a quad-state check box 071 // in "partial" state. 072 initialState = QuadStateCheckBox.State.PARTIAL; 073 } 074 075 final List<QuadStateCheckBox.State> allowedStates = new ArrayList<>(4); 076 if (QuadStateCheckBox.State.PARTIAL.equals(initialState)) 077 allowedStates.add(QuadStateCheckBox.State.PARTIAL); 078 allowedStates.add(QuadStateCheckBox.State.SELECTED); 079 if (!disable_off || value_off.equals(oneValue)) 080 allowedStates.add(QuadStateCheckBox.State.NOT_SELECTED); 081 allowedStates.add(QuadStateCheckBox.State.UNSET); 082 check = new QuadStateCheckBox(locale_text, initialState, 083 allowedStates.toArray(new QuadStateCheckBox.State[allowedStates.size()])); 084 085 p.add(check, GBC.eol().fill(GBC.HORIZONTAL)); 086 return true; 087 } 088 089 @Override 090 public void addCommands(List<Tag> changedTags) { 091 // if the user hasn't changed anything, don't create a command. 092 if (check.getState() == initialState && def == null) return; 093 094 // otherwise change things according to the selected value. 095 changedTags.add(new Tag(key, 096 check.getState() == QuadStateCheckBox.State.SELECTED ? value_on : 097 check.getState() == QuadStateCheckBox.State.NOT_SELECTED ? value_off : 098 null)); 099 } 100 101 @Override 102 public MatchType getDefaultMatch() { 103 return MatchType.NONE; 104 } 105 106 @Override 107 public Collection<String> getValues() { 108 return disable_off ? Arrays.asList(value_on) : Arrays.asList(value_on, value_off); 109 } 110 111 @Override 112 public String toString() { 113 return "Check [" 114 + (locale_text != null ? "locale_text=" + locale_text + ", " : "") 115 + (value_on != null ? "value_on=" + value_on + ", " : "") 116 + (value_off != null ? "value_off=" + value_off + ", " : "") 117 + "default_=" + default_ + ", " 118 + (check != null ? "check=" + check + ", " : "") 119 + (initialState != null ? "initialState=" + initialState 120 + ", " : "") + "def=" + def + ']'; 121 } 122}