// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.conflict.pair.nodes; import java.awt.Color; import java.awt.Component; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.border.Border; import javax.swing.table.TableCellRenderer; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.gui.DefaultNameFormatter; import org.openstreetmap.josm.gui.conflict.pair.ListMergeModel; import org.openstreetmap.josm.tools.ImageProvider; /** * This is the {@see TableCellRenderer} used in the node tables of {@see NodeListMerger}. * */ public class NodeListTableCellRenderer extends JLabel implements TableCellRenderer { //static private final Logger logger = Logger.getLogger(NodeListTableCellRenderer.class.getName()); //private static DecimalFormat COORD_FORMATTER = new DecimalFormat("###0.0000"); public final static Color BGCOLOR_SELECTED = new Color(143,170,255); public final static Color BGCOLOR_EMPTY_ROW = new Color(234,234,234); public final static Color BGCOLOR_FROZEN = new Color(234,234,234); public final static Color BGCOLOR_PARTICIPAING_IN_COMPARISON = Color.BLACK; public final static Color FGCOLOR_PARTICIPAING_IN_COMPARISON = Color.WHITE; public final static Color BGCOLOR_NOT_IN_OPPOSITE = new Color(255,197,197); public final static Color BGCOLOR_IN_OPPOSITE = new Color(255,234,213); public final static Color BGCOLOR_SAME_POSITION_IN_OPPOSITE = new Color(217,255,217); private final ImageIcon icon; private final Border rowNumberBorder; /** * constructor */ public NodeListTableCellRenderer() { icon = ImageProvider.get("data", "node"); rowNumberBorder = BorderFactory.createEmptyBorder(0,4,0,0); setOpaque(true); } /** * build the tool tip text for an {@see OsmPrimitive}. It consist of the formatted * key/value pairs for this primitive. * * @param primitive * @return the tool tip text */ public String buildToolTipText(OsmPrimitive primitive) { StringBuilder sb = new StringBuilder(); sb.append("<html>"); // show the id // sb.append("<strong>id</strong>=") .append(primitive.getId()) .append("<br>"); // show the key/value-pairs, sorted by key // ArrayList<String> keyList = new ArrayList<String>(primitive.keySet()); Collections.sort(keyList); for (int i = 0; i < keyList.size(); i++) { if (i > 0) { sb.append("<br>"); } String key = keyList.get(i); sb.append("<strong>") .append(key) .append("</strong>") .append("="); // make sure long values are split into several rows. Otherwise // the tool tip window can become to wide // String value = primitive.get(key); while(value.length() != 0) { sb.append(value.substring(0,Math.min(50, value.length()))); if (value.length() > 50) { sb.append("<br>"); value = value.substring(50); } else { value = ""; } } } sb.append("</html>"); return sb.toString(); } /** * reset the renderer */ protected void reset() { setBackground(Color.WHITE); setForeground(Color.BLACK); } /** * render a node * @param model the model * @param node the node * @param isSelected true, if the current row is selected */ protected void renderNode(ListMergeModel<Node>.EntriesTableModel model, Node node, int row, boolean isSelected) { setIcon(icon); setBorder(null); if (model.getListMergeModel().isFrozen()) { setBackground(BGCOLOR_FROZEN); } else if (isSelected) { setBackground(BGCOLOR_SELECTED); } else if (model.isParticipatingInCurrentComparePair()) { if (model.isSamePositionInOppositeList(row)) { setBackground(BGCOLOR_SAME_POSITION_IN_OPPOSITE); } else if (model.isIncludedInOppositeList(row)) { setBackground(BGCOLOR_IN_OPPOSITE); } else { setBackground(BGCOLOR_NOT_IN_OPPOSITE); } } setText(node.getDisplayName(DefaultNameFormatter.getInstance())); setToolTipText(buildToolTipText(node)); } /** * render an empty row */ protected void renderEmptyRow() { setIcon(null); setBackground(BGCOLOR_EMPTY_ROW); setText(""); } /** * render the row id * @param model the model * @param row the row index * @param isSelected true, if the current row is selected */ protected void renderRowId( ListMergeModel<Node>.EntriesTableModel model, int row, boolean isSelected) { setIcon(null); setBorder(rowNumberBorder); if (model.getListMergeModel().isFrozen()) { setBackground(BGCOLOR_FROZEN); } else if (model.isParticipatingInCurrentComparePair()) { setBackground(BGCOLOR_PARTICIPAING_IN_COMPARISON); setForeground(FGCOLOR_PARTICIPAING_IN_COMPARISON); } setText(Integer.toString(row+1)); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Node node = (Node)value; reset(); switch(column) { case 0: renderRowId(getModel(table),row, isSelected); break; case 1: if (node == null) { renderEmptyRow(); } else { renderNode(getModel(table), node, row, isSelected); } break; default: // should not happen throw new RuntimeException(MessageFormat.format("Unexpected column index. Got {0}.", column)); } return this; } /** * replies the model * @param table the table * @return the table model */ @SuppressWarnings("unchecked") protected ListMergeModel<Node>.EntriesTableModel getModel(JTable table) { return (ListMergeModel.EntriesTableModel)table.getModel(); } }