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 final ImageIcon iconDecided;
028    private final ImageIcon iconUndecided;
029    private final DefaultComboBoxModel<Object> model;
030    private final 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     * @param decision conflict resolution decision
112     */
113    protected void renderToolTipText(MultiValueResolutionDecision decision) {
114        String toolTipText = null;
115        switch (decision.getDecisionType()) {
116        case UNDECIDED:
117            toolTipText = tr("Please decide which values to keep");
118            break;
119        case KEEP_ONE:
120            toolTipText = tr("Value ''{0}'' is going to be applied for key ''{1}''",
121                    decision.getChosenValue(), decision.getKey());
122            break;
123        case SUM_ALL_NUMERIC:
124            toolTipText = tr("All numeric values sumed as ''{0}'' are going to be applied for key ''{1}''",
125                    decision.getChosenValue(), decision.getKey());
126            break;
127        case KEEP_NONE:
128            toolTipText = tr("The key ''{0}'' and all its values are going to be removed", decision.getKey());
129            break;
130        case KEEP_ALL:
131            toolTipText = tr("All values joined as ''{0}'' are going to be applied for key ''{1}''",
132                    decision.getChosenValue(), decision.getKey());
133            break;
134        }
135        setToolTipText(toolTipText);
136        cbDecisionRenderer.setToolTipText(toolTipText);
137    }
138
139    protected void reset() {
140        setFont(UIManager.getFont("Table.font"));
141        setIcon(null);
142        setText("");
143    }
144
145    @Override
146    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
147
148        reset();
149        if (value == null)
150            return this;
151
152        MultiValueResolutionDecision decision = (MultiValueResolutionDecision) value;
153        TagConflictResolverModel tagModel = (TagConflictResolverModel) table.getModel();
154        boolean conflict = tagModel.getKeysWithConflicts().contains(tagModel.getKey(row));
155        renderColors(decision, isSelected, conflict);
156        renderToolTipText(decision);
157        switch(column) {
158        case 0:
159            if (decision.isDecided()) {
160                setIcon(iconDecided);
161            } else {
162                setIcon(iconUndecided);
163            }
164            return this;
165
166        case 1:
167            setText(decision.getKey());
168            return this;
169
170        case 2:
171            renderValue(decision);
172            return cbDecisionRenderer;
173        }
174        return this;
175    }
176}