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}