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                    default:
069                        Main.error("Unknown decision type: "+decision.getDecisionType());
070                    }
071                } else {
072                    setForeground(UIManager.getColor("Table.foreground"));
073                    setBackground(UIManager.getColor("Table.background"));
074                }
075                break;
076            }
077        }
078    }
079
080    protected void renderValue(MultiValueResolutionDecision decision) {
081        model.removeAllElements();
082        switch (decision.getDecisionType()) {
083        case UNDECIDED:
084            model.addElement(tr("Choose a value"));
085            cbDecisionRenderer.setFont(getFont().deriveFont(Font.ITALIC));
086            cbDecisionRenderer.setSelectedIndex(0);
087            break;
088        case KEEP_ONE:
089            model.addElement(decision.getChosenValue());
090            cbDecisionRenderer.setFont(getFont());
091            cbDecisionRenderer.setSelectedIndex(0);
092            break;
093        case KEEP_NONE:
094            model.addElement(tr("deleted"));
095            cbDecisionRenderer.setFont(getFont().deriveFont(Font.ITALIC));
096            cbDecisionRenderer.setSelectedIndex(0);
097            break;
098        case KEEP_ALL:
099            model.addElement(decision.getChosenValue());
100            cbDecisionRenderer.setFont(getFont());
101            cbDecisionRenderer.setSelectedIndex(0);
102            break;
103        }
104    }
105
106    /**
107     * Sets the text of the tooltip for both renderers, this (the JLabel) and the combobox renderer.
108     */
109    protected void renderToolTipText(MultiValueResolutionDecision decision) {
110        String toolTipText;
111        switch (decision.getDecisionType()) {
112        case UNDECIDED:
113            toolTipText = tr("Please decide which values to keep");
114            setToolTipText(toolTipText);
115            cbDecisionRenderer.setToolTipText(toolTipText);
116            break;
117        case KEEP_ONE:
118            toolTipText = tr("Value ''{0}'' is going to be applied for key ''{1}''", decision.getChosenValue(), decision.getKey());
119            setToolTipText(toolTipText);
120            cbDecisionRenderer.setToolTipText(toolTipText);
121            break;
122        case KEEP_NONE:
123            toolTipText = tr("The key ''{0}'' and all its values are going to be removed", decision.getKey());
124            setToolTipText(toolTipText);
125            cbDecisionRenderer.setToolTipText(toolTipText);
126            break;
127        case KEEP_ALL:
128            toolTipText = tr("All values joined as ''{0}'' are going to be applied for key ''{1}''", decision.getChosenValue(), decision.getKey());
129            setToolTipText(toolTipText);
130            cbDecisionRenderer.setToolTipText(toolTipText);
131            break;
132        }
133    }
134
135    protected void reset() {
136        setFont(UIManager.getFont("Table.font"));
137        setIcon(null);
138        setText("");
139    }
140
141    @Override
142    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
143
144        reset();
145        if (value == null)
146            return this;
147
148        MultiValueResolutionDecision decision = (MultiValueResolutionDecision)value;
149        TagConflictResolverModel tagModel = (TagConflictResolverModel) table.getModel();
150        boolean conflict = tagModel.getKeysWithConflicts().contains(tagModel.getKey(row));
151        renderColors(decision, isSelected, conflict);
152        renderToolTipText(decision);
153        switch(column) {
154        case 0:
155            if (decision.isDecided()) {
156                setIcon(iconDecided);
157            } else {
158                setIcon(iconUndecided);
159            }
160            return this;
161
162        case 1:
163            setText(decision.getKey());
164            return this;
165
166        case 2:
167            renderValue(decision);
168            return cbDecisionRenderer;
169        }
170        return this;
171    }
172}