001: package net.suberic.pooka.gui.propedit;
002:
003: import net.suberic.pooka.*;
004: import net.suberic.util.*;
005: import net.suberic.util.gui.propedit.*;
006: import net.suberic.pooka.gui.propedit.*;
007: import net.suberic.util.gui.*;
008: import javax.swing.*;
009: import java.awt.event.*;
010: import java.awt.Cursor;
011: import javax.swing.Action;
012:
013: /**
014: * A property editor which edits an AddressBook.
015: */
016: public class AddressBookEditorPane extends SwingPropertyEditor {
017:
018: AddressBook book;
019: String bookName;
020: JPanel editPanel;
021: JPanel searchEntryPanel;
022: JTextField searchEntryField;
023: JTable addressTable;
024: JButton editButton, addButton, deleteButton, searchButton;
025: boolean enabled = true;
026:
027: PropertyEditorManager manager;
028:
029: Action[] defaultActions = new Action[] { new AddAction(),
030: new EditAction(), new DeleteAction() };
031:
032: ConfigurablePopupMenu popupMenu;
033:
034: /**
035: * @param propertyName The property to be edited.
036: * @param template The property that will define the layout of the
037: * editor.
038: * @param manager The PropertyEditorManager that will manage the
039: * changes.
040: * @param isEnabled Whether or not this editor is enabled by default.
041: */
042: public void configureEditor(String propertyName, String template,
043: PropertyEditorManager newManager, boolean isEnabled) {
044: property = propertyName;
045: manager = newManager;
046: editorTemplate = template;
047: originalValue = manager.getProperty(property, "");
048:
049: // we're going to have "AddressBook." at the beginning, and
050: // ".addressListEditor" at the end...
051: bookName = property.substring(12, property.length() - 18);
052: book = Pooka.getAddressBookManager().getAddressBook(bookName);
053:
054: this .setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
055: this .setBorder(BorderFactory.createEtchedBorder());
056:
057: createSearchEntryPanel();
058: createEditPanel();
059: createAddressTable();
060:
061: labelComponent = this ;
062:
063: this .add(searchEntryPanel);
064: //this.add(new JScrollPane(addressTable));
065: JScrollPane addressPane = new JScrollPane(addressTable);
066: try {
067: addressPane.setPreferredSize(new java.awt.Dimension(Integer
068: .parseInt(manager.getProperty(
069: "Pooka.addressBookEditor.hsize", "300")),
070: Integer.parseInt(manager.getProperty(
071: "Pooka.addressBookEditor.vsize", "100"))));
072: } catch (Exception e) {
073: addressPane.setPreferredSize(new java.awt.Dimension(300,
074: 100));
075: }
076: this .add(addressPane);
077: this .add(editPanel);
078:
079: popupMenu = new ConfigurablePopupMenu();
080: popupMenu.configureComponent("AddressBookEditor.popupMenu",
081: manager.getFactory().getSourceBundle());
082: popupMenu.setActive(getActions());
083:
084: this .setEnabled(isEnabled);
085: }
086:
087: /**
088: * Creates the panel which has the entry fields -- i.e., "Enter string to
089: * match", an entry field, and a search button.
090: */
091: public void createSearchEntryPanel() {
092: searchEntryPanel = new JPanel();
093: searchEntryPanel.add(new JLabel(manager.getProperty(
094: "AddressBookEditor.matchString", "Match String: ")));
095:
096: searchEntryField = new JTextField(30);
097: searchEntryPanel.add(searchEntryField);
098:
099: Action a = new SearchAction();
100:
101: searchButton = new JButton(manager.getProperty(
102: "AddressBookEditor.title.Search", "Search"));
103: searchButton.addActionListener(a);
104: searchEntryPanel.add(searchButton);
105:
106: }
107:
108: /**
109: * Creates the AddressTable.
110: */
111: public void createAddressTable() {
112: addressTable = new JTable();
113: addressTable.setCellSelectionEnabled(false);
114: addressTable.setColumnSelectionAllowed(false);
115: addressTable.setRowSelectionAllowed(true);
116:
117: addressTable.addMouseListener(new MouseAdapter() {
118: public void mouseClicked(MouseEvent e) {
119: if (e.getClickCount() == 2) {
120: int rowIndex = addressTable
121: .rowAtPoint(e.getPoint());
122: if (rowIndex != -1) {
123: addressTable.setRowSelectionInterval(rowIndex,
124: rowIndex);
125: AddressBookEntry selectedEntry = getSelectedEntry();
126: if (selectedEntry != null) {
127: editEntry(selectedEntry);
128: }
129: }
130: }
131: }
132:
133: public void mousePressed(MouseEvent e) {
134: if (e.isPopupTrigger()) {
135: // see if anything is selected
136: int rowIndex = addressTable
137: .rowAtPoint(e.getPoint());
138: if (rowIndex == -1
139: || !addressTable.isRowSelected(rowIndex)) {
140: addressTable.setRowSelectionInterval(rowIndex,
141: rowIndex);
142: }
143:
144: showPopupMenu(addressTable, e);
145: }
146: }
147:
148: public void mouseReleased(MouseEvent e) {
149: if (e.isPopupTrigger()) {
150: // see if anything is selected
151: int rowIndex = addressTable
152: .rowAtPoint(e.getPoint());
153: if (rowIndex == -1
154: || !addressTable.isRowSelected(rowIndex)) {
155: addressTable.setRowSelectionInterval(rowIndex,
156: rowIndex);
157: }
158:
159: showPopupMenu(addressTable, e);
160: }
161: }
162: });
163:
164: updateTableModel(new AddressBookEntry[0]);
165:
166: }
167:
168: /**
169: * Creates the panel which has the editor fields, such as add/delete/edit
170: * buttons.
171: */
172: public void createEditPanel() {
173: editPanel = new JPanel();
174:
175: Action a = new AddAction();
176: addButton = new JButton(manager.getProperty(
177: "AddressBookEditor.title.Add", "Add"));
178: addButton.addActionListener(a);
179: editPanel.add(addButton);
180:
181: a = new EditAction();
182: editButton = new JButton(manager.getProperty(
183: "AddressBookEditor.title.Edit", "Edit"));
184: editButton.addActionListener(a);
185: editPanel.add(editButton);
186:
187: a = new DeleteAction();
188: deleteButton = new JButton(manager.getProperty(
189: "AddressBookEditor.title.Delete", "Delete"));
190: deleteButton.addActionListener(a);
191: editPanel.add(deleteButton);
192:
193: }
194:
195: /**
196: * Performs a search using the string value in the searchEntryField. Updates
197: * the addressTable with the results.
198: */
199: public void performSearch() {
200: AddressBookEntry[] matchingEntries = book.getAddressMatcher()
201: .match(searchEntryField.getText());
202: updateTableModel(matchingEntries);
203: }
204:
205: /**
206: * Adds a new entry.
207: */
208: public void performAdd() {
209: AddressBookEntry newEntry = new net.suberic.pooka.vcard.Vcard(
210: new java.util.Properties());
211: try {
212: newEntry
213: .setAddresses(new javax.mail.internet.InternetAddress[] { new javax.mail.internet.InternetAddress(
214: "example@example.com") });
215: } catch (Exception e) {
216: }
217: if (newEntry.getAddresses() != null) {
218: book.addAddress(newEntry);
219: ((AddressBookTableModel) addressTable.getModel())
220: .addEntry(newEntry);
221: }
222: editEntry(newEntry);
223: }
224:
225: /**
226: * Edits the current entry.
227: */
228: public void performEdit() {
229: AddressBookEntry e = getSelectedEntry();
230: if (e != null)
231: editEntry(e);
232: }
233:
234: /**
235: * Deletes the current entry.
236: */
237: public void performDelete() {
238: AddressBookEntry e = getSelectedEntry();
239: if (e != null) {
240: book.removeAddress(e);
241: ((AddressBookTableModel) addressTable.getModel())
242: .removeEntry(e);
243: }
244: }
245:
246: /**
247: * Gets the currently selected entry.
248: */
249: public AddressBookEntry getSelectedEntry() {
250: int index = addressTable.getSelectedRow();
251: if (index > -1)
252: return ((AddressBookTableModel) addressTable.getModel())
253: .getEntryAt(index);
254: else
255: return null;
256: }
257:
258: /**
259: * Brings up an editor for the current entry.
260: */
261: public void editEntry(AddressBookEntry entry) {
262: AddressEntryEditor editor = new AddressEntryEditor(manager,
263: entry);
264: manager.getFactory().showNewEditorWindow(
265: manager.getProperty("AddressEntryEditor.title",
266: "Address Entry"), editor);
267: }
268:
269: /**
270: * Brings up the current popup menu.
271: */
272: public void showPopupMenu(JComponent component, MouseEvent e) {
273: popupMenu.show(component, e.getX(), e.getY());
274: }
275:
276: /**
277: * Updates the TableModel with the new entries.
278: */
279: public void updateTableModel(AddressBookEntry[] entries) {
280: AddressBookTableModel newTableModel = new AddressBookTableModel(
281: entries);
282: addressTable.setModel(newTableModel);
283: }
284:
285: public void setValue() {
286: if (book != null) {
287: try {
288: book.saveAddressBook();
289: } catch (Exception e) {
290: Pooka.getUIFactory().showError(
291: Pooka.getProperty(
292: "error.AddressBook.saveAddressBook",
293: "Error saving Address Book: ")
294: + e.getMessage());
295: e.printStackTrace();
296: }
297: } else {
298: // if we're setting the value on this editor, then we might also be
299: // creating the edited AddressBook. see if that's true.
300: SwingUtilities.invokeLater(new Runnable() {
301: public void run() {
302: AddressBook newBook = Pooka.getAddressBookManager()
303: .getAddressBook(bookName);
304: if (newBook != null) {
305: book = newBook;
306: setEnabled(true);
307: }
308: }
309: });
310: }
311: }
312:
313: public java.util.Properties getValue() {
314: return new java.util.Properties();
315: }
316:
317: public void resetDefaultValue() {
318: try {
319: book.loadAddressBook();
320: } catch (Exception e) {
321: Pooka.getUIFactory().showError(
322: Pooka.getProperty(
323: "error.AddressBook.loadAddressBook",
324: "Error reloading Address Book: ")
325: + e.getMessage());
326: e.printStackTrace();
327: }
328: performSearch();
329: }
330:
331: public boolean isChanged() {
332: return false;
333: }
334:
335: public void setEnabled(boolean newValue) {
336: if (book != null)
337: enabled = newValue;
338: else
339: enabled = false;
340:
341: searchButton.setEnabled(enabled);
342: addButton.setEnabled(enabled);
343: editButton.setEnabled(enabled);
344: deleteButton.setEnabled(enabled);
345: searchEntryField.setEnabled(enabled);
346: }
347:
348: public void setBusy(boolean newValue) {
349: if (newValue)
350: this .setCursor(Cursor
351: .getPredefinedCursor(Cursor.WAIT_CURSOR));
352: else
353: this .setCursor(Cursor
354: .getPredefinedCursor(Cursor.DEFAULT_CURSOR));
355: }
356:
357: public class AddressBookTableModel extends
358: javax.swing.table.AbstractTableModel {
359:
360: AddressBookEntry[] entries;
361:
362: public AddressBookTableModel(AddressBookEntry[] newEntries) {
363: entries = newEntries;
364: }
365:
366: public int getRowCount() {
367: return entries.length;
368: }
369:
370: public int getColumnCount() {
371: return 4;
372: }
373:
374: public String getColumnName(int index) {
375: if (index == 0) {
376: return Pooka.getProperty(
377: "AddressBookTable.personalName", "Name");
378: } else if (index == 1) {
379: return Pooka.getProperty("AddressBookTable.firstName",
380: "First Name");
381: } else if (index == 2) {
382: return Pooka.getProperty("AddressBookTable.lastName",
383: "Last Name");
384: } else if (index == 3) {
385: return Pooka.getProperty("AddressBookTable.address",
386: "Email Address");
387: } else {
388: return null;
389: }
390: }
391:
392: public Object getValueAt(int row, int column) {
393: if (row < 0 || column < 0 || row >= getRowCount()
394: || column >= getColumnCount())
395: return null;
396:
397: AddressBookEntry currentEntry = entries[row];
398:
399: if (column == 0) {
400: return currentEntry.getID();
401: }
402: if (column == 1) {
403: return currentEntry.getFirstName();
404: }
405: if (column == 2) {
406: return currentEntry.getLastName();
407: }
408: if (column == 3) {
409: return currentEntry.getAddressString();
410: }
411:
412: return null;
413: }
414:
415: /**
416: * Returns the AddressBookEntry at the given index.
417: */
418: public AddressBookEntry getEntryAt(int index) {
419: return entries[index];
420: }
421:
422: /**
423: * Adds the given AddressBookEntry to the end of the table.
424: */
425: public void addEntry(AddressBookEntry e) {
426: AddressBookEntry[] newEntries;
427: int length;
428:
429: if (entries != null) {
430: length = entries.length;
431: newEntries = new AddressBookEntry[length + 1];
432: System.arraycopy(entries, 0, newEntries, 0, length);
433: } else {
434: length = 0;
435: newEntries = new AddressBookEntry[1];
436: }
437: newEntries[length] = e;
438:
439: entries = newEntries;
440:
441: fireTableRowsInserted(length, length);
442: }
443:
444: /**
445: * Removes the given AddressBookEntry from the table, if present.
446: */
447: public void removeEntry(AddressBookEntry e) {
448: boolean found = false;
449:
450: for (int i = 0; !found && i < entries.length; i++) {
451: if (e == entries[i]) {
452: found = true;
453: int removedRow = i;
454: AddressBookEntry[] newEntries = new AddressBookEntry[entries.length - 1];
455: if (removedRow != 0)
456: System.arraycopy(entries, 0, newEntries, 0,
457: removedRow);
458:
459: if (removedRow != entries.length - 1)
460: System.arraycopy(entries, removedRow + 1,
461: newEntries, removedRow, entries.length
462: - removedRow - 1);
463:
464: entries = newEntries;
465: fireTableRowsDeleted(removedRow, removedRow);
466: }
467: }
468: }
469: }
470:
471: /**
472: * Returns the actions associated with this editor.
473: */
474: public Action[] getActions() {
475: return defaultActions;
476: }
477:
478: public class SearchAction extends AbstractAction {
479: public SearchAction() {
480: super ("address-search");
481: }
482:
483: public void actionPerformed(ActionEvent e) {
484: setBusy(true);
485: performSearch();
486: setBusy(false);
487: }
488: }
489:
490: public class AddAction extends AbstractAction {
491: public AddAction() {
492: super ("address-add");
493: }
494:
495: public void actionPerformed(ActionEvent e) {
496: setBusy(true);
497: performAdd();
498: setBusy(false);
499: }
500: }
501:
502: public class EditAction extends AbstractAction {
503: public EditAction() {
504: super ("address-edit");
505: }
506:
507: public void actionPerformed(ActionEvent e) {
508: setBusy(true);
509: performEdit();
510: setBusy(false);
511: }
512: }
513:
514: public class DeleteAction extends AbstractAction {
515: public DeleteAction() {
516: super ("address-delete");
517: }
518:
519: public void actionPerformed(ActionEvent e) {
520: setBusy(true);
521: performDelete();
522: setBusy(false);
523: }
524: }
525:
526: }
|