001 package org.springframework.richclient.widget.table; 002 003 import org.apache.commons.beanutils.NestedNullException; 004 import org.apache.commons.beanutils.PropertyUtils; 005 import org.jdesktop.swingx.renderer.DefaultTableRenderer; 006 import org.jdesktop.swingx.renderer.FormatStringValue; 007 import org.springframework.richclient.util.RcpSupport; 008 009 import javax.swing.*; 010 import javax.swing.border.Border; 011 import javax.swing.border.EmptyBorder; 012 import javax.swing.table.DefaultTableCellRenderer; 013 import javax.swing.table.JTableHeader; 014 import javax.swing.table.TableCellRenderer; 015 import java.awt.*; 016 import java.math.BigDecimal; 017 import java.text.*; 018 import java.util.Collection; 019 import java.util.Date; 020 import java.util.Locale; 021 022 /** 023 * Voorziet een paar eenvoudige renderers voor gebruiksgemak. 024 */ 025 public class TableCellRenderers 026 { 027 028 public static final TableCellRenderer CENTER_ALIGNED_RENDERER = new AlignedRenderer(SwingConstants.CENTER); 029 030 public static final TableCellRenderer RIGHT_ALIGNED_RENDERER = new AlignedRenderer(SwingConstants.RIGHT); 031 032 public static final TableCellRenderer TOP_ALIGNED_RENDERER = new AlignedRenderer(SwingConstants.LEFT, 033 SwingConstants.TOP); 034 public static final TableCellRenderer BOTTOM_ALIGNED_RENDERER = new AlignedRenderer(SwingConstants.LEFT, 035 SwingConstants.BOTTOM); 036 public static final TableCellRenderer PERCENTAGE_RENDERER = new PercentageRenderer(); 037 public static final TableCellRenderer MONEY_RENDERER = new BigDecimalRenderer(NumberFormat 038 .getCurrencyInstance(Locale.getDefault())); 039 public static final TableCellRenderer LEFT_ALIGNED_HEADER_RENDERER = new AlignedTableHeaderRenderer( 040 SwingConstants.LEFT); 041 public static final TableCellRenderer CENTER_ALIGNED_HEADER_RENDERER = new AlignedTableHeaderRenderer( 042 SwingConstants.CENTER); 043 public static final TableCellRenderer RIGHT_ALIGNED_HEADER_RENDERER = new AlignedTableHeaderRenderer( 044 SwingConstants.RIGHT); 045 public static final TableCellRenderer ENUM_RENDERER = new EnumTableCellRenderer(); 046 047 public static final TableCellRenderer FLAT_NUMBER_RENDERER = new FlatNumberRenderer(); 048 049 public static class FlatNumberRenderer extends DefaultTableRenderer 050 { 051 052 private static NumberFormat format = NumberFormat.getIntegerInstance(); 053 static 054 { 055 format.setGroupingUsed(false); 056 } 057 058 public FlatNumberRenderer() 059 { 060 super(new FormatStringValue(format)); 061 } 062 } 063 064 public static class AlignedRenderer extends DefaultTableCellRenderer 065 { 066 067 public AlignedRenderer(int horizontalAlignment) 068 { 069 super(); 070 setHorizontalAlignment(horizontalAlignment); 071 } 072 073 public AlignedRenderer(int horizontalAlignment, int verticalAlignment) 074 { 075 super(); 076 setHorizontalAlignment(horizontalAlignment); 077 setVerticalAlignment(verticalAlignment); 078 } 079 080 DateFormat formatter; 081 082 @Override 083 public void setValue(Object value) 084 { 085 if (value != null && value instanceof Date) 086 { 087 if (formatter == null) 088 { 089 formatter = DateFormat.getDateInstance(); 090 } 091 setText(formatter.format(value)); 092 } 093 else 094 { 095 super.setValue(value); 096 } 097 } 098 099 } 100 101 public static class PercentageRenderer extends DefaultTableCellRenderer 102 { 103 104 private static final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.getDefault()); 105 private static final Format nonFractionalFormat = new DecimalFormat("### %", symbols); 106 private static final Format fractionalFormat = new DecimalFormat("##0.00%", symbols); 107 private static final BigDecimal multiplyFactor = new BigDecimal("100"); 108 109 public PercentageRenderer() 110 { 111 setHorizontalAlignment(SwingConstants.RIGHT); 112 } 113 114 @Override 115 protected void setValue(Object value) 116 { 117 if (value instanceof BigDecimal) 118 { 119 BigDecimal percentage = ((BigDecimal) value).multiply(multiplyFactor); 120 if (percentage.doubleValue() == percentage.intValue()) 121 { 122 super.setValue(nonFractionalFormat.format(value)); 123 } 124 else 125 { 126 super.setValue(fractionalFormat.format(value)); 127 } 128 } 129 else 130 { 131 super.setValue(value); 132 } 133 } 134 } 135 136 public static class BigDecimalRenderer extends DefaultTableCellRenderer 137 { 138 139 private final BigDecimal multiplyFactor; 140 private final Format format; 141 142 public BigDecimalRenderer(Format format) 143 { 144 this(null, format); 145 } 146 147 public BigDecimalRenderer(BigDecimal multiplyFactor) 148 { 149 this(multiplyFactor, NumberFormat.getNumberInstance()); 150 } 151 152 public BigDecimalRenderer(BigDecimal multiplyFactor, Format format) 153 { 154 this(multiplyFactor, format, SwingConstants.RIGHT); 155 } 156 157 public BigDecimalRenderer(BigDecimal multiplyFactor, Format format, int horizontalAlignment) 158 { 159 this.multiplyFactor = multiplyFactor; 160 this.format = format; 161 setHorizontalAlignment(horizontalAlignment); 162 } 163 164 @Override 165 protected void setValue(Object value) 166 { 167 if (value instanceof BigDecimal) 168 { 169 if (multiplyFactor != null) 170 { 171 value = ((BigDecimal) value).multiply(multiplyFactor); 172 } 173 super.setValue(format.format(value)); 174 } 175 else 176 { 177 super.setValue(value); 178 } 179 } 180 } 181 182 public static class AlignedTableHeaderRenderer extends DefaultTableCellRenderer 183 { 184 185 private int align = SwingConstants.CENTER; 186 187 public AlignedTableHeaderRenderer(int align) 188 { 189 this.align = align; 190 } 191 192 @Override 193 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 194 boolean hasFocus, int row, int column) 195 { 196 if (table != null) 197 { 198 JTableHeader header = table.getTableHeader(); 199 if (header != null) 200 { 201 setForeground(header.getForeground()); 202 setBackground(header.getBackground()); 203 setFont(header.getFont()); 204 } 205 } 206 207 setText((value == null) ? "" : value.toString() + " "); 208 setBorder(UIManager.getBorder("TableHeader.cellBorder")); 209 setHorizontalAlignment(align); 210 return this; 211 } 212 } 213 214 public static class EnumTableCellRenderer extends DefaultTableCellRenderer 215 { 216 217 public EnumTableCellRenderer() 218 { 219 super(); 220 } 221 222 @Override 223 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 224 boolean hasFocus, int row, int column) 225 { 226 227 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 228 229 if (value == null) 230 { 231 setValue(""); 232 setIcon(null); 233 } 234 else 235 { 236 if (value instanceof Enum) 237 { 238 Enum valueEnum = (Enum) value; 239 Class<? extends Enum> valueClass = valueEnum.getClass(); 240 setValue(RcpSupport.getMessage(valueClass.getName() + "." + valueEnum.name())); 241 setIcon(RcpSupport.getIcon(valueClass.getName() + "." + valueEnum.name())); 242 } 243 else 244 { 245 setValue(value); 246 } 247 } 248 return this; 249 } 250 } 251 252 public static class ListPropertyCellRenderer extends JPanel implements TableCellRenderer 253 { 254 255 protected String property; 256 257 protected int verticalAlignment; 258 259 protected int horizontalAlignment; 260 261 protected Format format; 262 263 protected float alignmentX; 264 265 private static Border border = new EmptyBorder(1, 2, 1, 2); 266 267 public ListPropertyCellRenderer(String property) 268 { 269 this(property, SwingConstants.LEFT, SwingConstants.CENTER); 270 } 271 272 public ListPropertyCellRenderer(String property, int horizontalAlignment, int verticalAlignment) 273 { 274 this(property, horizontalAlignment, verticalAlignment, null); 275 } 276 277 public ListPropertyCellRenderer(String property, int horizontalAlignment, int verticalAlignment, 278 Format format) 279 { 280 this.property = property; 281 this.horizontalAlignment = horizontalAlignment; 282 this.verticalAlignment = verticalAlignment; 283 this.format = format; 284 switch (horizontalAlignment) 285 { 286 case SwingConstants.LEFT : 287 alignmentX = (float) 0.0; 288 break; 289 290 case SwingConstants.CENTER : 291 alignmentX = (float) 0.5; 292 break; 293 294 case SwingConstants.RIGHT : 295 alignmentX = (float) 1.0; 296 break; 297 298 default : 299 throw new IllegalArgumentException("Illegal horizontal alignment value"); 300 } 301 302 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 303 setOpaque(true); 304 setBorder(border); 305 } 306 307 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 308 boolean hasFocus, int row, int column) 309 { 310 removeAll(); 311 invalidate(); 312 313 Color fg = table.getForeground(); 314 Color bg = table.getBackground(); 315 316 if (isSelected) 317 { 318 fg = table.getSelectionForeground(); 319 bg = table.getSelectionBackground(); 320 } 321 322 Font font = table.getFont(); 323 324 setFont(font); 325 326 if (hasFocus) 327 { 328 Border border = null; 329 if (isSelected) 330 { 331 border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder"); 332 } 333 if (border == null) 334 { 335 border = UIManager.getBorder("Table.focusCellHighlightBorder"); 336 } 337 setBorder(border); 338 339 if (!isSelected && table.isCellEditable(row, column)) 340 { 341 Color col; 342 col = UIManager.getColor("Table.focusCellForeground"); 343 if (col != null) 344 { 345 fg = col; 346 } 347 col = UIManager.getColor("Table.focusCellBackground"); 348 if (col != null) 349 { 350 bg = col; 351 } 352 } 353 } 354 else 355 { 356 setBorder(border); 357 } 358 359 super.setForeground(fg); 360 super.setBackground(bg); 361 362 if (verticalAlignment != SwingConstants.TOP) 363 { 364 add(Box.createVerticalGlue()); 365 } 366 367 Object[] values; 368 if (value instanceof Collection) 369 { 370 values = ((Collection) value).toArray(); 371 } 372 else 373 throw new IllegalArgumentException("Value must be an instance of Collection."); 374 375 for (int i = 0; i < values.length; i++) 376 { 377 Object o = values[i]; 378 Object line; 379 try 380 { 381 line = PropertyUtils.getProperty(o, property); 382 } 383 catch (NestedNullException e) 384 { 385 line = null; 386 } 387 catch (Exception e) 388 { 389 throw new RuntimeException("Error reading property " + property + " from object " + o, e); 390 } 391 JLabel lineLabel = new JLabel(); 392 lineLabel.setForeground(fg); 393 lineLabel.setFont(font); 394 setValue(lineLabel, line, i); 395 add(lineLabel); 396 } 397 398 int height_wanted = (int) getPreferredSize().getHeight(); 399 if (height_wanted > table.getRowHeight(row)) 400 table.setRowHeight(row, height_wanted); 401 402 if (verticalAlignment != SwingConstants.BOTTOM) 403 { 404 add(Box.createVerticalGlue()); 405 } 406 return this; 407 } 408 409 protected void setValue(JLabel l, Object value, int lineNumber) 410 { 411 if (format != null && value != null) 412 value = format.format(value); 413 l.setText(value == null ? " " : value.toString()); 414 l.setHorizontalAlignment(horizontalAlignment); 415 l.setAlignmentX(alignmentX); 416 l.setOpaque(false); 417 } 418 419 } 420 } 421