001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.conflict.pair.relation;
003
004import java.awt.Color;
005import java.awt.Component;
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.List;
009
010import javax.swing.BorderFactory;
011import javax.swing.JLabel;
012import javax.swing.JTable;
013import javax.swing.border.Border;
014import javax.swing.table.TableCellRenderer;
015
016import org.openstreetmap.josm.data.osm.Node;
017import org.openstreetmap.josm.data.osm.OsmPrimitive;
018import org.openstreetmap.josm.data.osm.RelationMember;
019import org.openstreetmap.josm.gui.DefaultNameFormatter;
020import org.openstreetmap.josm.gui.conflict.ConflictColors;
021import org.openstreetmap.josm.gui.conflict.pair.ListMergeModel;
022import org.openstreetmap.josm.tools.ImageProvider;
023
024/**
025 * This is the {@link TableCellRenderer} used in the tables of {@link RelationMemberMerger}.
026 *
027 */
028public  class RelationMemberTableCellRenderer extends JLabel implements TableCellRenderer {
029    private  Border rowNumberBorder = null;
030
031    /**
032     * constructor
033     */
034    public RelationMemberTableCellRenderer() {
035        setIcon(null);
036        setOpaque(true);
037        rowNumberBorder = BorderFactory.createEmptyBorder(0,4,0,0);
038    }
039
040    public String buildToolTipText(OsmPrimitive primitive) {
041        StringBuilder sb = new StringBuilder();
042        sb.append("<html>");
043        sb.append("<strong>id</strong>=")
044        .append(primitive.getId())
045        .append("<br>");
046        List<String> keyList = new ArrayList<String>(primitive.keySet());
047        Collections.sort(keyList);
048        for (int i = 0; i < keyList.size(); i++) {
049            if (i > 0) {
050                sb.append("<br>");
051            }
052            String key = keyList.get(i);
053            sb.append("<strong>")
054            .append(key)
055            .append("</strong>")
056            .append("=");
057            String value = primitive.get(key);
058            while(value.length() != 0) {
059                sb.append(value.substring(0,Math.min(50, value.length())));
060                if (value.length() > 50) {
061                    sb.append("<br>");
062                    value = value.substring(50);
063                } else {
064                    value = "";
065                }
066            }
067        }
068        sb.append("</html>");
069        return sb.toString();
070    }
071
072    /**
073     * reset the renderer
074     */
075    protected void reset() {
076        setBackground(ConflictColors.BGCOLOR.get());
077        setForeground(ConflictColors.FGCOLOR.get());
078        setBorder(null);
079        setIcon(null);
080        setToolTipText(null);
081    }
082
083    protected void renderBackground(ListMergeModel<Node>.EntriesTableModel model, RelationMember member, int row, int col, boolean isSelected) {
084        Color bgc = ConflictColors.BGCOLOR.get();
085        if (col == 0) {
086            if (model.getListMergeModel().isFrozen()) {
087                bgc = ConflictColors.BGCOLOR_FROZEN.get();
088            } else if (model.isParticipatingInCurrentComparePair()) {
089                bgc = ConflictColors.BGCOLOR_PARTICIPAING_IN_COMPARISON.get();
090            } else if (isSelected) {
091                bgc = ConflictColors.BGCOLOR_SELECTED.get();
092            }
093        } else {
094            if (model.getListMergeModel().isFrozen()) {
095                bgc = ConflictColors.BGCOLOR_FROZEN.get();
096            } else if (member == null) {
097                bgc = ConflictColors.BGCOLOR_EMPTY_ROW.get();
098            } else if (isSelected) {
099                bgc = ConflictColors.BGCOLOR_SELECTED.get();
100            } else {
101                if (model.isParticipatingInCurrentComparePair()) {
102                    if (model.isSamePositionInOppositeList(row)) {
103                        bgc = ConflictColors.BGCOLOR_SAME_POSITION_IN_OPPOSITE.get();
104                    } else if (model.isIncludedInOppositeList(row)) {
105                        bgc = ConflictColors.BGCOLOR_IN_OPPOSITE.get();
106                    } else {
107                        bgc = ConflictColors.BGCOLOR_NOT_IN_OPPOSITE.get();
108                    }
109                }
110            }
111        }
112        setBackground(bgc);
113    }
114
115    protected void renderForeground(ListMergeModel<Node>.EntriesTableModel model, RelationMember member, int row, int col, boolean isSelected) {
116        Color fgc = ConflictColors.FGCOLOR.get();
117        if (col == 0 && model.isParticipatingInCurrentComparePair() && ! model.getListMergeModel().isFrozen()) {
118            fgc = ConflictColors.FGCOLOR_PARTICIPAING_IN_COMPARISON.get();
119        }
120        setForeground(fgc);
121    }
122
123    protected void renderRole(RelationMember member) {
124        setText(member.getRole());
125        setToolTipText(member.getRole());
126    }
127
128    protected void renderPrimitive(RelationMember member) {
129        String displayName = member.getMember().getDisplayName(DefaultNameFormatter.getInstance());
130        setText(displayName);
131        setToolTipText(buildToolTipText(member.getMember()));
132        setIcon(ImageProvider.get(member.getDisplayType()));
133    }
134
135    /**
136     * render the row id
137     * @param row the row index
138     */
139    protected  void renderRowId(int row) {
140        setBorder(rowNumberBorder);
141        setText(Integer.toString(row+1));
142    }
143
144    protected void renderEmptyRow() {
145        setIcon(null);
146        setBackground(ConflictColors.BGCOLOR_EMPTY_ROW.get());
147        setText("");
148    }
149
150    @Override
151    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
152            int row, int column) {
153
154        RelationMember member = (RelationMember)value;
155        reset();
156        if (member == null) {
157            renderEmptyRow();
158        } else {
159            renderBackground(getModel(table), member, row, column, isSelected);
160            renderForeground(getModel(table), member, row, column, isSelected);
161            switch(column) {
162            case 0:
163                renderRowId(row);
164                break;
165            case 1:
166                renderRole(member);
167                break;
168            case 2:
169                renderPrimitive(member);
170                break;
171            default:
172                // should not happen
173            }
174        }
175        return this;
176    }
177
178    /**
179     * replies the model
180     * @param table  the table
181     * @return the table model
182     */
183    @SuppressWarnings("unchecked")
184    protected ListMergeModel<Node>.EntriesTableModel getModel(JTable table) {
185        return (ListMergeModel.EntriesTableModel)table.getModel();
186    }
187}