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