001: package org.zilonis.tool.ui;
002:
003: import java.awt.Color;
004: import java.awt.Component;
005: import java.awt.Font;
006: import java.awt.FontMetrics;
007: import java.util.Arrays;
008: import java.util.LinkedList;
009: import java.util.List;
010:
011: import javax.swing.GroupLayout;
012: import javax.swing.JLabel;
013: import javax.swing.JList;
014: import javax.swing.ListCellRenderer;
015: import javax.swing.border.EmptyBorder;
016: import javax.swing.border.LineBorder;
017:
018: import org.jdesktop.swingx.JXPanel;
019: import org.zilonis.tool.ext.mailman.ui.JImagePanel;
020: import org.zilonis.tool.ext.mailman.ui.MailTable;
021:
022: public class WMEListCellRenderer implements ListCellRenderer {
023: private static final int IS = 48;
024: private static final Color FROM_COLOR = new Color(244, 244, 244);
025:
026: public WMEListCellRenderer() {
027:
028: }
029:
030: public Component getListCellRendererComponent(JList list,
031: Object value, int index, boolean isSelected,
032: boolean cellHasFocus) {
033: final RendererPanel panel = new RendererPanel();
034: panel.setOpaque(false);
035: if (value instanceof WMEMetaData) {
036: panel.setWMETemplate((WMEMetaData) value);
037: } else {
038: panel.setWMETemplate(null);
039: }
040: if (isSelected) {
041: adjustColors(panel, list.getSelectionBackground(), list
042: .getSelectionForeground());
043: panel.setOpaque(true);
044: } else {
045: panel.setOpaque(false);
046: adjustColors(panel, list.getBackground(), list
047: .getForeground());
048: if ((index % 2) == 0) {
049: panel.setBackground(MailTable.STRIPE_COLOR);
050: }
051: panel.fromLabel.setForeground(FROM_COLOR);
052: for (Component c : panel.labels) {
053: c.setForeground(Color.WHITE);
054: }
055: }
056: return panel;
057: }
058:
059: private void adjustColors(RendererPanel panel, Color bg, Color fg) {
060: for (Component c : panel.toAdjust) {
061: c.setForeground(fg);
062: c.setBackground(bg);
063: }
064: }
065:
066: private int getRowCount() {
067: return 2;
068: }
069:
070: private class RendererPanel extends JXPanel {
071: private final JLabel dateLabel;
072: private final JLabel labels[];
073: private final JLabel fromLabel;
074: private final JImagePanel imagePanel;
075: private final JLabel subjectLabel;
076: private final List<Component> toAdjust;
077: private final char[] tmpChars;
078: private String text;
079: private int layoutWidth;
080:
081: RendererPanel() {
082: tmpChars = new char[512];
083: setBorder(new EmptyBorder(4, 4, 4, 4));
084: setOpaque(true);
085: fromLabel = new JLabel(" ");
086: fromLabel.setForeground(FROM_COLOR);
087: fromLabel.setFont(fromLabel.getFont().deriveFont(
088: Font.ITALIC));
089: subjectLabel = new JLabel("a");
090: dateLabel = new JLabel("");
091: dateLabel
092: .setFont(dateLabel.getFont().deriveFont(Font.BOLD));
093: Font f = subjectLabel.getFont();
094: subjectLabel.setForeground(Color.WHITE);
095: subjectLabel.setFont(f.deriveFont(Font.BOLD,
096: f.getSize() + 4f));
097: labels = new JLabel[getRowCount()];
098: for (int i = 0; i < getRowCount(); i++) {
099: labels[i] = new JLabel(" ");
100: }
101: imagePanel = new JImagePanel();
102: imagePanel.setBorder(new LineBorder(Color.BLACK, 1));
103: imagePanel.setEditable(false);
104:
105: GroupLayout layout = new GroupLayout(this );
106: setLayout(layout);
107:
108: GroupLayout.ParallelGroup labelHG = layout
109: .createParallelGroup();
110: GroupLayout.SequentialGroup labelVG = layout
111: .createSequentialGroup();
112: for (int i = 0; i < labels.length; i++) {
113: if (i > 0) {
114: labelVG.addGap(0);
115: }
116: if (i < labels.length - 1) {
117: labelHG.addComponent(labels[i], 0, 0,
118: Integer.MAX_VALUE);
119: labelVG.addComponent(labels[i]);
120: }
121: }
122: labelVG.addGroup(layout.createParallelGroup(
123: GroupLayout.Alignment.BASELINE).addComponent(
124: labels[labels.length - 1], 0, 0, Integer.MAX_VALUE)
125: .addComponent(fromLabel));
126: labelHG.addGroup(layout.createSequentialGroup()
127: .addComponent(labels[labels.length - 1], 0, 0,
128: Integer.MAX_VALUE).addComponent(fromLabel));
129: GroupLayout.SequentialGroup hg = layout
130: .createSequentialGroup();
131: hg.addComponent(imagePanel, IS, IS, IS).addGroup(
132: layout.createParallelGroup().addGroup(
133: layout.createSequentialGroup()
134: .addComponent(subjectLabel, 0, 0,
135: Integer.MAX_VALUE)
136: .addComponent(dateLabel)).addGroup(
137: labelHG));
138: layout.setHorizontalGroup(hg);
139:
140: GroupLayout.ParallelGroup vg = layout.createParallelGroup();
141: vg.addComponent(imagePanel, GroupLayout.Alignment.CENTER,
142: IS, IS, IS).addGroup(
143: layout.createSequentialGroup().addGroup(
144: layout.createParallelGroup(
145: GroupLayout.Alignment.BASELINE)
146: .addComponent(subjectLabel)
147: .addComponent(dateLabel)).addGap(0)
148: .addGroup(labelVG));
149: layout.setVerticalGroup(vg);
150: // layout.setAutoCreateContainerGaps(true);
151: layout.setAutoCreateGaps(true);
152:
153: toAdjust = new LinkedList<Component>();
154: toAdjust.add(dateLabel);
155: toAdjust.addAll(Arrays.asList(labels));
156: toAdjust.add(this );
157: toAdjust.add(fromLabel);
158: }
159:
160: public void setWMETemplate(WMEMetaData m) {
161: if (m == null) {
162: text = null;
163: subjectLabel.setText(" ");
164: fromLabel.setText(" ");
165: resetMessageLabels();
166: } else {
167: subjectLabel.setText(m.getClazz());
168: imagePanel.setImage(null);
169: text = "";
170: String attributes[] = m.getAttribute();
171: for (int i = 0; i < attributes.length; ++i) {
172: text += attributes[i];
173: if (i < attributes.length - 1)
174: text += ", ";
175: }
176: reflowText();
177: //dateLabel.setText(text);
178: //fromLabel.setText(text);
179: }
180: }
181:
182: public void doLayout() {
183: super .doLayout();
184: if (layoutWidth != getWidth()) {
185: layoutWidth = getWidth();
186: reflowText();
187: }
188: }
189:
190: private int nextNonWhitespace(int index, int length) {
191: while (index < length
192: && Character.isWhitespace(tmpChars[index])) {
193: tmpChars[index] = ' ';
194: index++;
195: }
196: return index;
197: }
198:
199: private int nextWhitespace(int index, int length) {
200: while (index < length
201: && !Character.isWhitespace(tmpChars[index])) {
202: index++;
203: }
204: return index;
205: }
206:
207: private void resetMessageLabels() {
208: for (JLabel label : labels) {
209: label.setText(" ");
210: }
211: }
212:
213: private void reflowText() {
214: resetMessageLabels();
215: int availableWidth = labels[0].getWidth();
216: if (availableWidth > 0 && text != null) {
217: int charCount = Math
218: .min(tmpChars.length, text.length());
219: text.getChars(0, charCount, tmpChars, 0);
220: FontMetrics fm = labels[0].getFontMetrics(labels[0]
221: .getFont());
222: int lineStart = nextNonWhitespace(0, charCount);
223: int lastChunkThatFits = lineStart;
224: int lineIndex = 0;
225: int index = lineStart;
226: boolean tooLong = false;
227: while (!tooLong && index < charCount
228: && lineIndex < labels.length) {
229: index = nextWhitespace(index, charCount);
230: int charWidth = fm.charsWidth(tmpChars, lineStart,
231: index - lineStart);
232: if (charWidth < availableWidth) {
233: lastChunkThatFits = index;
234: index = nextNonWhitespace(index, charCount);
235: } else if (lastChunkThatFits == lineStart) {
236: tooLong = true;
237: } else {
238: // charWidth > availableWidth, lastChunkThatFits != lineStart
239: labels[lineIndex++].setText(new String(
240: tmpChars, lineStart, lastChunkThatFits
241: - lineStart));
242: lineStart = nextNonWhitespace(
243: lastChunkThatFits, charCount);
244: lastChunkThatFits = lineStart;
245: }
246: }
247: if (!tooLong && lineIndex < labels.length
248: && lineStart != charCount) {
249: labels[lineIndex].setText(new String(tmpChars,
250: lineStart, charCount - lineStart));
251: }
252: }
253: }
254: }
255: }
|