001: package org.columba.addressbook.gui.search;
002:
003: import java.awt.BorderLayout;
004: import java.awt.Color;
005: import java.awt.Component;
006: import java.awt.Graphics;
007: import java.awt.Insets;
008: import java.awt.Point;
009: import java.awt.event.ActionEvent;
010: import java.awt.event.ActionListener;
011: import java.awt.event.MouseAdapter;
012: import java.awt.event.MouseEvent;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import javax.swing.BorderFactory;
017: import javax.swing.DefaultListModel;
018: import javax.swing.JLabel;
019: import javax.swing.JList;
020: import javax.swing.JMenuItem;
021: import javax.swing.JPanel;
022: import javax.swing.JPopupMenu;
023: import javax.swing.ListCellRenderer;
024: import javax.swing.border.AbstractBorder;
025: import javax.swing.border.Border;
026:
027: import org.columba.addressbook.facade.DialogFacade;
028: import org.columba.api.exception.ServiceNotFoundException;
029: import org.columba.contact.search.ContactSearchResult;
030: import org.columba.core.facade.ServiceFacadeRegistry;
031: import org.columba.core.gui.base.DoubleClickListener;
032: import org.columba.core.resourceloader.IconKeys;
033: import org.columba.core.resourceloader.ImageLoader;
034: import org.columba.core.search.api.ISearchResult;
035: import org.jdesktop.swingx.JXHyperlink;
036: import org.jdesktop.swingx.JXList;
037: import org.jdesktop.swingx.decorator.Highlighter;
038: import org.jdesktop.swingx.decorator.HighlighterPipeline;
039: import org.jdesktop.swingx.decorator.RolloverHighlighter;
040:
041: public class SearchResultList extends JXList {
042:
043: private DefaultListModel listModel;
044: private JPopupMenu contextMenu;
045:
046: public SearchResultList() {
047: super ();
048:
049: listModel = new DefaultListModel();
050: setModel(listModel);
051: setCellRenderer(new MyListCellRenderer());
052:
053: setBorder(null);
054: setHighlighters(new HighlighterPipeline(
055: new Highlighter[] { new RolloverHighlighter(new Color(
056: 248, 248, 248), Color.white) }));
057: setRolloverEnabled(true);
058:
059: addMouseListener(new DoubleClickListener() {
060: @Override
061: public void doubleClick(MouseEvent event) {
062: ISearchResult selected = (ISearchResult) getSelectedValue();
063: new DialogFacade().openContactDialog(selected
064: .getLocation());
065: }
066: });
067:
068: add(getPopupMenu());
069: addMouseListener(new MyMouseListener());
070: }
071:
072: private JPopupMenu getPopupMenu() {
073: if (contextMenu != null)
074: return contextMenu;
075:
076: contextMenu = new JPopupMenu();
077:
078: JMenuItem item = new JMenuItem("Open..");
079: item.addActionListener(new ActionListener() {
080: public void actionPerformed(ActionEvent event) {
081: ISearchResult selected = (ISearchResult) getSelectedValue();
082: new DialogFacade().openContactDialog(selected
083: .getLocation());
084: }
085: });
086: contextMenu.add(item);
087:
088: item = new JMenuItem("Compose Message..");
089: item.addActionListener(new ActionListener() {
090: public void actionPerformed(ActionEvent event) {
091: ContactSearchResult selected = (ContactSearchResult) getSelectedValue();
092:
093: String address = selected.getDescription();
094:
095: try {
096: org.columba.mail.facade.IDialogFacade facade = (org.columba.mail.facade.IDialogFacade) ServiceFacadeRegistry
097: .getInstance()
098: .getService(
099: org.columba.mail.facade.IDialogFacade.class);
100: facade.openComposer(address);
101: } catch (ServiceNotFoundException e) {
102: e.printStackTrace();
103: }
104: }
105: });
106:
107: contextMenu.add(item);
108: return contextMenu;
109: }
110:
111: public void addAll(List<ISearchResult> result) {
112: Iterator<ISearchResult> it = result.iterator();
113: while (it.hasNext()) {
114: listModel.addElement(it.next());
115: }
116: }
117:
118: public void add(ISearchResult result) {
119: listModel.addElement(result);
120: }
121:
122: public void clear() {
123: listModel.clear();
124: }
125:
126: class MyMouseListener extends MouseAdapter {
127:
128: @Override
129: public void mouseClicked(MouseEvent e) {
130: handleEvent(e);
131: }
132:
133: @Override
134: public void mousePressed(MouseEvent e) {
135: handlePopupEvent(e);
136: }
137:
138: @Override
139: public void mouseReleased(MouseEvent e) {
140: handlePopupEvent(e);
141: }
142:
143: /**
144: * @param e
145: */
146: private void handlePopupEvent(MouseEvent e) {
147: Point p = e.getPoint();
148: if (e.isPopupTrigger()) {
149: // check if a single entry is selected
150: if (getSelectedIndices().length <= 1) {
151: // select new item
152: int index = locationToIndex(p);
153: setSelectedIndex(index);
154: }
155: // show context menu
156: getPopupMenu().show(e.getComponent(), p.x, p.y);
157: }
158: }
159:
160: /**
161: * @param e
162: */
163: private void handleEvent(MouseEvent e) {
164: }
165: }
166:
167: class MyListCellRenderer extends JPanel implements ListCellRenderer {
168:
169: private JLabel iconLabel = new JLabel();
170:
171: private JLabel titleLabel = new JLabel();
172:
173: private JXHyperlink descriptionLabel = new JXHyperlink();
174:
175: private JPanel centerPanel;
176:
177: private Border lineBorder = new HeaderSeparatorBorder(
178: new Color(230, 230, 230));
179:
180: MyListCellRenderer() {
181: setLayout(new BorderLayout());
182:
183: centerPanel = new JPanel();
184: centerPanel.setLayout(new BorderLayout());
185:
186: centerPanel.add(titleLabel, BorderLayout.NORTH);
187: centerPanel.add(descriptionLabel, BorderLayout.CENTER);
188: add(iconLabel, BorderLayout.WEST);
189: add(centerPanel, BorderLayout.CENTER);
190:
191: setBorder(BorderFactory.createCompoundBorder(lineBorder,
192: BorderFactory.createEmptyBorder(2, 2, 2, 2)));
193: iconLabel.setBorder(BorderFactory.createEmptyBorder(2, 4,
194: 2, 8));
195:
196: centerPanel.setOpaque(false);
197: setOpaque(true);
198:
199: }
200:
201: public Component getListCellRendererComponent(JList list,
202: Object value, int index, boolean isSelected,
203: boolean cellHasFocus) {
204:
205: if (isSelected) {
206: setBackground(list.getSelectionBackground());
207: setForeground(list.getSelectionForeground());
208:
209: } else {
210: setBackground(list.getBackground());
211: setForeground(list.getForeground());
212:
213: }
214:
215: ISearchResult result = (ISearchResult) value;
216:
217: titleLabel.setText(result.getTitle());
218: iconLabel.setIcon(ImageLoader.getSmallIcon(IconKeys.USER));
219: descriptionLabel.setText(result.getDescription());
220:
221: return this ;
222: }
223:
224: }
225:
226: class HeaderSeparatorBorder extends AbstractBorder {
227:
228: protected Color color;
229:
230: public HeaderSeparatorBorder(Color color) {
231: super ();
232:
233: this .color = color;
234: }
235:
236: /**
237: * Paints the border for the specified component with the specified
238: * position and size.
239: *
240: * @param c
241: * the component for which this border is being painted
242: * @param g
243: * the paint graphics
244: * @param x
245: * the x position of the painted border
246: * @param y
247: * the y position of the painted border
248: * @param width
249: * the width of the painted border
250: * @param height
251: * the height of the painted border
252: */
253: public void paintBorder(Component c, Graphics g, int x, int y,
254: int width, int height) {
255: Color oldColor = g.getColor();
256: g.setColor(color);
257: g
258: .drawLine(x, y + height - 1, x + width - 1, y
259: + height - 1);
260:
261: g.setColor(oldColor);
262: }
263:
264: /**
265: * Returns the insets of the border.
266: *
267: * @param c
268: * the component for which this border insets value applies
269: */
270: public Insets getBorderInsets(Component c) {
271: return new Insets(0, 0, 1, 0);
272: }
273:
274: /**
275: * Reinitialize the insets parameter with this Border's current Insets.
276: *
277: * @param c
278: * the component for which this border insets value applies
279: * @param insets
280: * the object to be reinitialized
281: */
282: public Insets getBorderInsets(Component c, Insets insets) {
283: insets.left = insets.top = insets.right = insets.bottom = 1;
284: return insets;
285: }
286:
287: }
288: }
|