001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.conflict.tags;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Component;
007import java.awt.Font;
008
009import javax.swing.DefaultComboBoxModel;
010import javax.swing.ImageIcon;
011import javax.swing.JLabel;
012import javax.swing.JTable;
013import javax.swing.UIManager;
014import javax.swing.table.TableCellRenderer;
015
016import org.openstreetmap.josm.Main;
017import org.openstreetmap.josm.gui.conflict.ConflictColors;
018import org.openstreetmap.josm.gui.widgets.JosmComboBox;
019import org.openstreetmap.josm.tools.ImageProvider;
020
021/**
022 * This is a {@link TableCellRenderer} for {@link MultiValueResolutionDecision}s.
023 *
024 */
025public class MultiValueCellRenderer extends JLabel implements TableCellRenderer {
026
027    private ImageIcon iconDecided;
028    private ImageIcon iconUndecided;
029    private DefaultComboBoxModel<Object> model;
030    private JosmComboBox<Object> cbDecisionRenderer;
031
032    /**
033     * Constructs a new {@code MultiValueCellRenderer}.
034     */
035    public MultiValueCellRenderer() {
036        setOpaque(true);
037        iconDecided = ImageProvider.get("dialogs/conflict", "tagconflictresolved");
038        iconUndecided = ImageProvider.get("dialogs/conflict", "tagconflictunresolved");
039        model = new DefaultComboBoxModel<>();
040        cbDecisionRenderer = new JosmComboBox<>(model);
041    }
042
043    protected void renderColors(MultiValueResolutionDecision decision, boolean selected, boolean conflict) {
044        if (selected) {
045            setForeground(UIManager.getColor("Table.selectionForeground"));
046            setBackground(UIManager.getColor("Table.selectionBackground"));
047        } else {
048            switch (decision.getDecisionType()) {
049            case UNDECIDED:
050                setForeground(ConflictColors.FGCOLOR_UNDECIDED.get());
051                setBackground(ConflictColors.BGCOLOR_UNDECIDED.get());
052                break;
053            case KEEP_NONE:
054                setForeground(ConflictColors.FGCOLOR_TAG_KEEP_NONE.get());
055                setBackground(ConflictColors.BGCOLOR_TAG_KEEP_NONE.get());
056                break;
057            default:
058                if (conflict) {
059                    switch (decision.getDecisionType()) {
060                    case KEEP_ONE:
061                        setForeground(ConflictColors.FGCOLOR_TAG_KEEP_ONE.get());
062                        setBackground(ConflictColors.BGCOLOR_TAG_KEEP_ONE.get());
063                        break;
064                    case KEEP_ALL:
065                        setForeground(ConflictColors.FGCOLOR_TAG_KEEP_ALL.get());
066                        setBackground(ConflictColors.BGCOLOR_TAG_KEEP_ALL.get());
067                        break;
068                    case SUM_ALL_NUMERIC:
069                        setForeground(ConflictColors.FGCOLOR_TAG_SUM_ALL_NUM.get());
070                        setBackground(ConflictColors.BGCOLOR_TAG_SUM_ALL_NUM.get());
071                        break;
072                    default:
073                        Main.error("Unknown decision type in renderColors(): "+decision.getDecisionType());
074                    }
075                } else {
076                    setForeground(UIManager.getColor("Table.foreground"));
077                    setBackground(UIManager.getColor("Table.background"));
078                }
079                break;
080            }
081        }
082    }
083
084    protected void renderValue(MultiValueResolutionDecision decision) {
085        model.removeAllElements();
086        switch (decision.getDecisionType()) {
087        case UNDECIDED:
088            model.addElement(tr("Choose a value"));
089            cbDecisionRenderer.setFont(getFont().deriveFont(Font.ITALIC));
090            cbDecisionRenderer.setSelectedIndex(0);
091            break;
092        case KEEP_NONE:
093            model.addElement(tr("deleted"));
094            cbDecisionRenderer.setFont(getFont().deriveFont(Font.ITALIC));
095            cbDecisionRenderer.setSelectedIndex(0);
096            break;
097        case KEEP_ONE:
098        case KEEP_ALL:
099        case SUM_ALL_NUMERIC:
100            model.addElement(decision.getChosenValue());
101            cbDecisionRenderer.setFont(getFont());
102            cbDecisionRenderer.setSelectedIndex(0);
103            break;
104        default:
105            Main.error("Unknown decision type in renderValue(): "+decision.getDecisionType());
106        }
107    }
108
109    /**
110     * Sets the text of the tooltip for both renderers, this (the JLabel) and the combobox renderer.
111     */
112    protected void renderToolTipText(MultiValueResolutionDecision decision) {
113        String toolTipText = null;
114        switch (decision.getDecisionType()) {
115        case UNDECIDED:
116            toolTipText = tr("Please decide which values to keep");
117            break;
118        case KEEP_ONE:
119            toolTipText = tr("Value ''{0}'' is going to be applied for key ''{1}''",
120                    decision.getChosenValue(), decision.getKey());
121            break;
122        case SUM_ALL_NUMERIC:
123            toolTipText = tr("All numeric values sumed as ''{0}'' are going to be applied for key ''{1}''",
124                    decision.getChosenValue(), decision.getKey());
125            break;
126        case KEEP_NONE:
127            toolTipText = tr("The key ''{0}'' and all its values are going to be removed", decision.getKey());
128            break;
129        case KEEP_ALL:
130            toolTipText = tr("All values joined as ''{0}'' are going to be applied for key ''{1}''",
131                    decision.getChosenValue(), decision.getKey());
132            break;
133        }
134        setToolTipText(toolTipText);
135        cbDecisionRenderer.setToolTipText(toolTipText);
136    }
137
138    protected void reset() {
139        setFont(UIManager.getFont("Table.font"));
140        setIcon(null);
141        setText("");
142    }
143
144    @Override
145    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
146
147        reset();
148        if (value == null)
149            return this;
150
151        MultiValueResolutionDecision decision = (MultiValueResolutionDecision) value;
152        TagConflictResolverModel tagModel = (TagConflictResolverModel) table.getModel();
153        boolean conflict = tagModel.getKeysWithConflicts().contains(tagModel.getKey(row));
154        renderColors(decision, isSelected, conflict);
155        renderToolTipText(decision);
156        switch(column) {
157        case 0:
158            if (decision.isDecided()) {
159                setIcon(iconDecided);
160            } else {
161                setIcon(iconUndecided);
162            }
163            return this;
164
165        case 1:
166            setText(decision.getKey());
167            return this;
168
169        case 2:
170            renderValue(decision);
171            return cbDecisionRenderer;
172        }
173        return this;
174    }
175}