// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.turnrestrictions.list; import static org.openstreetmap.josm.tools.I18n.tr; import static org.openstreetmap.josm.tools.I18n.trc; import java.awt.Color; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.ListCellRenderer; import javax.swing.UIManager; import javax.swing.table.TableCellRenderer; import org.openstreetmap.josm.data.Preferences; import org.openstreetmap.josm.data.osm.OsmPrimitiveType; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.data.osm.RelationMember; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.gui.DefaultNameFormatter; import org.openstreetmap.josm.gui.widgets.JMultilineLabel; import org.openstreetmap.josm.plugins.turnrestrictions.preferences.PreferenceKeys; import org.openstreetmap.josm.tools.ImageProvider; /** * This is a cell renderer for turn restrictions. * * It can be used a cell renderer in lists of turn restrictions and as cell renderer in * {@link JTable}s displaying turn restrictions. * */ public class TurnRestrictionCellRenderer extends JPanel implements ListCellRenderer<Relation>, TableCellRenderer { /** the names of restriction types */ private static Set<String> RESTRICTION_TYPES = new HashSet<>( Arrays.asList(new String[] { "no_left_turn", "no_right_turn", "no_straight_on", "no_u_turn", "only_left_turn", "only_right_turn", "only_straight_on" }) ); /** components used to render the turn restriction */ private JLabel icon; private JLabel from; private JLabel to; private String iconSet = "set-a"; public TurnRestrictionCellRenderer() { build(); } /** * Replies true if {@code restrictionType} is a valid restriction * type. * * @param restrictionType the restriction type * @return true if {@code restrictionType} is a valid restriction * type */ protected boolean isValidRestrictionType(String restrictionType) { if (restrictionType == null) return false; restrictionType = restrictionType.trim().toLowerCase(); return RESTRICTION_TYPES.contains(restrictionType); } /** * Builds the icon name for a given restriction type * * @param restrictionType the restriction type * @return the icon name */ protected String buildImageName(String restrictionType) { return "types/" + iconSet + "/" + restrictionType; } /** * Replies the icon for a given restriction type * @param restrictionType the restriction type * @return the icon */ protected ImageIcon getIcon(String restrictionType) { if (!isValidRestrictionType(restrictionType)) { return ImageProvider.get("types", "non-standard-type"); } return ImageProvider.get(buildImageName(restrictionType)); } /** * Builds the UI used to render turn restrictions */ protected void build() { setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); // the turn restriction icon gc.fill = GridBagConstraints.HORIZONTAL; gc.weightx = 0.0; gc.gridheight = 2; gc.anchor = GridBagConstraints.CENTER; gc.insets = new Insets(0, 0, 2, 2); add(icon = new JLabel(), gc); // the name of the way with role "from" gc.anchor = GridBagConstraints.NORTHWEST; gc.gridx = 1; gc.gridheight = 1; gc.weightx = 0.0; add(new JMultilineLabel("<html><strong>" + trc("turnrestrictions", "From:") + "</strong></html>"), gc); gc.gridx = 2; gc.weightx = 1.0; add(from = new JLabel(), gc); // the name of the way with role "to" gc.anchor = GridBagConstraints.NORTHWEST; gc.gridx = 1; gc.gridy = 1; gc.weightx = 0.0; add(new JMultilineLabel("<html><strong>" + trc("turnrestriction", "To:") + "</strong></html>"), gc); gc.gridx = 2; gc.weightx = 1.0; add(to = new JLabel(), gc); } /** * Renders the icon for the turn restriction * * @param tr the turn restriction */ protected void renderIcon(Relation tr) { String restrictionType = tr.get("restriction"); icon.setIcon(getIcon(restrictionType)); } /** * Replies a way participating in this turn restriction in a given role * * @param tr the turn restriction * @param role the role (either "from" or "to") * @return the participating way; null, if no way is participating in this role */ private Way getParticipatingWay(Relation tr, String role) { for (RelationMember rm: tr.getMembers()) { if (rm.getRole().trim().toLowerCase().equals(role) && rm.getType().equals(OsmPrimitiveType.WAY)) { return (Way) rm.getMember(); } } return null; } protected void renderFrom(Relation tr) { Way from = getParticipatingWay(tr, "from"); if (from == null) { // FIXME: render as warning/error (red background?) this.from.setText(tr("no participating way with role ''from''")); return; } this.from.setText(DefaultNameFormatter.getInstance().format(from)); } protected void renderTo(Relation tr) { Way to = getParticipatingWay(tr, "to"); if (to == null) { // FIXME: render as warning/error (red background?) this.to.setText(tr("no participating way with role ''to''")); return; } this.to.setText(DefaultNameFormatter.getInstance().format(to)); } /** * Renders the foreground and background color depending on whether * the turn restriction is selected * * @param isSelected true if the turn restriction is selected; false, * otherwise */ protected void renderColor(boolean isSelected) { Color bg; Color fg; if (isSelected) { bg = UIManager.getColor("List.selectionBackground"); fg = UIManager.getColor("List.selectionForeground"); } else { bg = UIManager.getColor("background"); fg = UIManager.getColor("foreground"); } setBackground(bg); this.icon.setBackground(bg); this.from.setBackground(bg); this.to.setBackground(bg); setForeground(fg); this.icon.setForeground(fg); this.from.setForeground(fg); this.to.setForeground(fg); } /** * Initializes the set of icons used from the preference key * {@link PreferenceKeys#ROAD_SIGNS}. * * @param prefs the JOSM preferences */ public void initIconSetFromPreferences(Preferences prefs) { iconSet = prefs.get(PreferenceKeys.ROAD_SIGNS, "set-a"); iconSet = iconSet.trim().toLowerCase(); if (!iconSet.equals("set-a") && !iconSet.equals("set-b")) { iconSet = "set-a"; } } /* ---------------------------------------------------------------------------------- */ /* interface ListCellRenderer */ /* ---------------------------------------------------------------------------------- */ @Override public Component getListCellRendererComponent(JList<? extends Relation> list, Relation value, int index, boolean isSelected, boolean cellHasFocus) { renderColor(isSelected); Relation tr = value; renderIcon(tr); renderFrom(tr); renderTo(tr); return this; } /* ---------------------------------------------------------------------------------- */ /* interface TableCellRenderer */ /* ---------------------------------------------------------------------------------- */ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { renderColor(isSelected); Relation tr = (Relation) value; renderIcon(tr); renderFrom(tr); renderTo(tr); return this; } }