Source code: com/cybertivity/powerjournal/MultiEntryView.java
1 package com.cybertivity.powerjournal;
2 import java.awt.BorderLayout;
3 import java.awt.Color;
4 import java.awt.FlowLayout;
5 import java.awt.Insets;
6 import java.awt.Point;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.MouseAdapter;
9 import java.awt.event.MouseEvent;
10 import java.awt.event.MouseListener;
11 import java.text.SimpleDateFormat;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Date;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.Map;
18 import java.util.Set;
19 import javax.swing.BorderFactory;
20 import javax.swing.JButton;
21 import javax.swing.JLabel;
22 import javax.swing.JPanel;
23 import javax.swing.JScrollPane;
24 import javax.swing.JTable;
25 import javax.swing.ListSelectionModel;
26 import javax.swing.SwingConstants;
27 import javax.swing.SwingUtilities;
28 import javax.swing.ToolTipManager;
29 import javax.swing.event.ListSelectionEvent;
30 import javax.swing.event.ListSelectionListener;
31 import javax.swing.table.*;
32 import com.cybertivity.powerjournal.framework.*;
33
34 /**
35 * Title: PowerJournal
36 * Description: $Id: MultiEntryView.java,v 1.3 2001/12/26 22:39:44 arrowood Exp $
37 * Copyright: Copyright (c) 2001
38 * Company: <A HREF="http://www.cybertivity.com">Cybertivity</A>
39 *
40 * @author <A HREF="mailto:chris.arrowood@cybertivity.com">Chris Arrowood</A>
41 * @created December 9, 2001
42 * @version 1.0
43 */
44
45 public class MultiEntryView extends EntryView implements ListSelectionListener, MouseListener {
46
47 private String appName = "";
48 private boolean guestMode = true;
49 private JPanel panelTitle = null;
50 private JPanel panelEntryGrid = null;
51 private JPanel panelControl = null;
52 private JTable table = null;
53 private SortFilterModel sorter;
54 private ArrayList entries = null;
55 private HashMap buttons = new HashMap();
56 public final static String EVENT_NEW = "New";
57 public final static String EVENT_DELETE = "Delete";
58 public final static String EVENT_VIEW_ENTRY = "View Entry";
59 public final static String EVENT_VIEW_SELECTED = "View Selected";
60
61
62 public MultiEntryView(String appNameArg, boolean guestModeArg, ArrayList entriesArg) {
63 appName = appNameArg;
64 guestMode = guestModeArg;
65 entries = entriesArg;
66 createWindow();
67 }
68
69
70 public void displayEntries(ArrayList entriesArg) {
71 entries = entriesArg;
72 createWindow();
73 enableControls();
74 }
75
76 protected void setGuestMode(boolean guestModeArg){
77 guestMode = guestModeArg;
78 }
79
80
81 protected String getSelectedEntryNumber() {
82 // Get the data model for this table
83 TableModel model = (TableModel) table.getModel();
84
85 // Determine the selected item
86 int row = table.getSelectedRow();
87 if (row == -1) {
88 return "";
89 } else {
90 Integer i = (Integer) model.getValueAt(row, 0);
91 return i.toString();
92 }
93 }
94
95
96 private void createWindow() {
97 content.removeAll();
98 BorderLayout layout = new BorderLayout();
99 content.setLayout(layout);
100 panelTitle = buildPanelTitle();
101 panelEntryGrid = buildPanelEntryGrid();
102 panelControl = buildPanelControl();
103 content.add(panelTitle, BorderLayout.NORTH);
104 content.add(panelEntryGrid, BorderLayout.CENTER);
105 content.add(panelControl, BorderLayout.SOUTH);
106 }
107
108
109 private JPanel buildPanelTitle() {
110 JPanel panel = new JPanel();
111 BorderLayout layout = new BorderLayout();
112 JLabel labelTitle = new JLabel();
113 labelTitle.setFont(new java.awt.Font("SansSerif", 1, 20));
114 labelTitle.setHorizontalAlignment(SwingConstants.CENTER);
115 labelTitle.setHorizontalTextPosition(SwingConstants.CENTER);
116 labelTitle.setText(appName);
117 panel.add(labelTitle, BorderLayout.CENTER);
118 return panel;
119 }
120
121
122 private JPanel buildPanelControl() {
123 //create JPanel
124 JPanel btnPanel = new JPanel();
125 FlowLayout btnPanelLayout = new FlowLayout();
126 btnPanel.setBorder(BorderFactory.createEtchedBorder());
127
128 //create buttons
129 JButton btnNew = makeButton(EVENT_NEW, EVENT_NEW, Color.blue);
130 JButton btnDelete = makeButton(EVENT_DELETE, EVENT_DELETE, Color.red);
131 JButton btnView = makeButton(EVENT_VIEW_SELECTED, EVENT_VIEW_SELECTED, Color.blue);
132 btnNew.setToolTipText("Create a new entry");
133 btnDelete.setToolTipText("Delete current entry");
134 btnView.setToolTipText("View the selected entry");
135
136 //add buttons
137 btnPanel.add(btnView, null);
138 btnPanel.add(btnNew, null);
139 btnPanel.add(btnDelete, null);
140
141 //create Jpanel for copyright info
142 JPanel copyrightPanel = new JPanel();
143 JLabel copyrightLabel = new JLabel("© 2001 Chris Arrowood");
144 copyrightLabel.setForeground(Color.darkGray);
145 copyrightPanel.add(copyrightLabel);
146
147 //glue all of it together
148 JPanel panel = new JPanel();
149 BorderLayout layout = new BorderLayout();
150 panel.setLayout(layout);
151 panel.add(btnPanel, BorderLayout.CENTER);
152 panel.add(copyrightPanel, BorderLayout.SOUTH);
153 return panel;
154 }
155
156
157 private JPanel buildPanelEntryGrid() {
158 JPanel panelEntryGrid = null;
159 BorderLayout layout = new BorderLayout();
160 panelEntryGrid = new JPanel();
161 panelEntryGrid.setLayout(layout);
162 table = buildEntryGrid();
163 JScrollPane scroll = new JScrollPane(table);
164 panelEntryGrid.add(scroll, BorderLayout.CENTER);
165 return panelEntryGrid;
166 }
167
168
169 private JTable buildEntryGrid() {
170 DataModel model = new DataModel(entries);
171 sorter = new SortFilterModel(model);
172 //create table and set attributes
173 JTable table = new JTable(sorter);
174 table.setCellSelectionEnabled(false);
175 table.setRowSelectionAllowed(true);
176 table.setColumnSelectionAllowed(false);
177 table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
178 table.setAutoResizeMode(table.AUTO_RESIZE_LAST_COLUMN);
179 table.setShowGrid(true);
180
181 // Handle the listener
182 ListSelectionModel selectionModel = table.getSelectionModel();
183 selectionModel.addListSelectionListener(this);
184
185 // Handle mouse events like double click
186 table.addMouseListener(this);
187
188 // set up double click handler for column headers
189 sorter.addMouseListener(table);
190
191 // Speed up the table by disabling tooltips
192 // From the JTable FAQ at http://www.chka.de/swing/table/faq.html
193 ToolTipManager.sharedInstance().unregisterComponent(table);
194 ToolTipManager.sharedInstance().unregisterComponent(table.getTableHeader());
195
196 //set coulumn attributes
197 TableColumnModel columnModel = table.getColumnModel();
198 for (int i = 0; i < model.getColumnCount(); i++) {
199 TableColumn thisColumn = columnModel.getColumn(i);
200 thisColumn.setPreferredWidth(model.getPreferredColumnWidth(i));
201 thisColumn.setResizable(model.getIsColumnResizable(i));
202 }
203 return table;
204 }
205
206
207
208 // Handler for list selection changes
209 // I do not think I wil be using this but I am leaving here for
210 // future reference
211 public void valueChanged(ListSelectionEvent event) {
212 // See if this is a valid table selection
213 if (event.getSource() == table.getSelectionModel()
214 && event.getFirstIndex() >= 0) {
215 // Get the data model for this table
216 TableModel model = (TableModel) table.getModel();
217
218 // Determine the selected item
219 // String string = (String) model.getValueAt(
220 // table.getSelectedRow(),
221 // table.getSelectedColumn());
222
223 // Sometimes it will fire twice
224 // However, you may also miss events by doing this!
225 if (!event.getValueIsAdjusting()) {
226 //System.out.println( "Value selected = " + string );
227 }
228 }
229 }
230
231
232 private JButton makeButton(String name, final String action, Color color) {
233 JButton btn = new JButton();
234 btn.setText(name);
235 if (color != null) {
236 btn.setForeground(color);
237 }
238
239 btn.addActionListener(
240 new java.awt.event.ActionListener() {
241 //private final String actionFinal = action;
242 public void actionPerformed(ActionEvent e) {
243 fireEvent(action);
244 }
245 });
246 if (buttons != null) {
247 buttons.put(name, btn);
248 }
249 return btn;
250 }
251
252
253 protected void cleanUp() { }
254
255
256 protected void enableControls() {
257 buttonsSetEnabled(true);
258 }
259
260
261 protected void displayEntry(Entry displayEntry, boolean guestModeArg) { }
262
263
264 protected void handleModelEvent(ModelEvent event) { }
265
266
267 protected void displayEntry(Entry displayEntry, boolean guestModeArg, boolean isNewEntry) { }
268
269
270 protected void disableControls() {
271 buttonsSetEnabled(false);
272 }
273
274
275 private void buttonsSetEnabled(boolean enable) {
276 Set set = buttons.keySet();
277 Iterator iter = set.iterator();
278 while (iter.hasNext()) {
279 String name = (String) iter.next();
280 JButton btn = (JButton) buttons.get(name);
281 if (guestMode && (name.equals(EVENT_NEW))) {
282 btn.setEnabled(false);
283 } else if (guestMode && (name.equals(EVENT_DELETE))) {
284 btn.setEnabled(false);
285 } else {
286 btn.setEnabled(enable);
287 }
288 }
289 }
290
291
292 class DataModel extends AbstractTableModel {
293
294 private ArrayList entriesToTabulate;
295 public final static int columnNameIndex = 0;
296 public final static int columnPreferredWidthIndex = 1;
297 public final static int columnIsResizeableIndex = 2;
298 public final static int columnClassTypeIndex = 3;
299 private final Object[][] columns = {
300 {"ID", new Integer(25), new Boolean(true), new Integer(0)},
301 {"Private", new Integer(45), new Boolean(true), new Boolean(true)},
302 {"Date", new Integer(150), new Boolean(true), ""},
303 {"Desc", new Integer(400), new Boolean(true), ""}
304 };
305
306
307 public DataModel(ArrayList arg) {
308 entriesToTabulate = arg;
309 }
310
311
312 public Class getColumnClass(int c) {
313 return columns[c][columnClassTypeIndex].getClass();
314 }
315
316
317 public int getRowCount() {
318 return entriesToTabulate.size();
319 }
320
321
322 public String getColumnName(int c) {
323 return (String) columns[c][columnNameIndex];
324 }
325
326
327 public int getColumnCount() {
328 return columns.length;
329 }
330
331
332 public int getPreferredColumnWidth(int col) {
333 Integer value = (Integer) columns[col][columnPreferredWidthIndex];
334 return value.intValue();
335 }
336
337
338 public boolean getIsColumnResizable(int col) {
339 Boolean value = (Boolean) columns[col][columnIsResizeableIndex];
340 return value.booleanValue();
341 }
342
343
344 public Object getValueAt(int row, int col) {
345 Object returnString = "Error";
346 Entry entry = (Entry) entries.get(row);
347 try {
348 if (col == 0) {
349 returnString = new Integer(entry.getEntryNumber());
350 } else if (col == 1) {
351 returnString = new Boolean(entry.getEntryPrivate());
352 } else if (col == 2) {
353 SimpleDateFormat df = new SimpleDateFormat(Entry.DATE_FORMAT);
354 returnString = df.format(new Date(entry.getEntryDate().getTime()));
355 } else if (col == 3) {
356 returnString = "" + entry.getEntryDescription();
357 }
358 } catch (NullPointerException npe) {
359 returnString = "(Null)";
360 }
361 return returnString;
362 }
363
364 }
365
366
367 class SortFilterModel extends AbstractTableModel {
368 public SortFilterModel(TableModel m) {
369 model = m;
370 rows = new Row[model.getRowCount()];
371 for (int i = 0; i < rows.length; i++) {
372 rows[i] = new Row();
373 rows[i].index = i;
374 }
375 }
376
377
378 public void sort(int c) {
379 sortColumn = c;
380 Arrays.sort(rows);
381 fireTableDataChanged();
382 }
383
384
385 public void addMouseListener(final JTable table) {
386 table.getTableHeader().addMouseListener(
387 new MouseAdapter() {
388 public void mouseClicked(MouseEvent event) {
389 // check for double click
390 // if (event.getClickCount() < 2) {
391 // return;
392 // }
393
394 // find column of click and
395 int tableColumn
396 = table.columnAtPoint(event.getPoint());
397
398 // translate to table model index and sort
399 int modelColumn
400 = table.convertColumnIndexToModel(tableColumn);
401 sort(modelColumn);
402 }
403 });
404 }
405
406
407 /*
408 * compute the moved row for the three methods that access
409 * model elements
410 */
411 public Object getValueAt(int r, int c) {
412 return model.getValueAt(rows[r].index, c);
413 }
414
415
416 public boolean isCellEditable(int r, int c) {
417 return model.isCellEditable(rows[r].index, c);
418 }
419
420
421 public void setValueAt(Object aValue, int r, int c) {
422 model.setValueAt(aValue, rows[r].index, c);
423 }
424
425
426 /*
427 * delegate all remaining methods to the model
428 */
429 public int getRowCount() {
430 return model.getRowCount();
431 }
432
433
434 public int getColumnCount() {
435 return model.getColumnCount();
436 }
437
438
439 public String getColumnName(int c) {
440 return model.getColumnName(c);
441 }
442
443
444 public Class getColumnClass(int c) {
445 return model.getColumnClass(c);
446 }
447
448
449 /*
450 * this inner class holds the index of the model row
451 * Rows are compared by looking at the model row entries
452 * in the sort column
453 */
454 private class Row implements Comparable {
455 /**
456 */
457 public int index;
458
459
460 public int compareTo(Object other) {
461 Row otherRow = (Row) other;
462 Object a = model.getValueAt(index, sortColumn);
463 Object b = model.getValueAt(otherRow.index, sortColumn);
464 if (a instanceof Comparable) {
465 return ((Comparable) a).compareTo(b);
466 } else {
467 return index - otherRow.index;
468 }
469 }
470 }
471
472
473 private TableModel model;
474 private int sortColumn;
475 private Row[] rows;
476 }
477
478
479 public void mouseClicked(MouseEvent e) {
480 if (e.getClickCount() == 2) {
481 Point p = e.getPoint();
482 int row = table.rowAtPoint(p);
483 int column = table.columnAtPoint(p);
484
485 TableModel model = (TableModel) table.getModel();
486 Integer lastEntryDoubleClicked = (Integer) model.getValueAt(table.getSelectedRow(), 0);
487 fireEvent(MultiEntryView.EVENT_VIEW_ENTRY, lastEntryDoubleClicked.toString());
488 }
489 }
490
491
492 public void mousePressed(MouseEvent e) { }
493
494
495 public void mouseReleased(MouseEvent e) { }
496
497
498 public void mouseEntered(MouseEvent e) { }
499
500
501 public void mouseExited(MouseEvent e) { }
502 }