/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2000 Michael Powers This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.ui.swing; import java.awt.BorderLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.border.EmptyBorder; import javax.swing.table.TableColumn; import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSNotification; import net.wotonomy.foundation.NSNotificationCenter; import net.wotonomy.foundation.NSSelector; import net.wotonomy.ui.EOAssociation; import net.wotonomy.ui.EODisplayGroup; import net.wotonomy.ui.swing.components.FormattedCellRenderer; import net.wotonomy.ui.swing.util.ObjectInspector; import net.wotonomy.ui.swing.util.StackTraceInspector; import net.wotonomy.ui.swing.util.WindowUtilities; import net.wotonomy.control.internal.Surrogate; /** * The NotificationInspector displays a JFrame that displays notifications as * they occur.
*
* * @author michael@mpowers.net * @version $Revision: 904 $ */ public class NotificationInspector implements MouseListener, ActionListener { protected JTable table; protected JPopupMenu popupMenu; protected EODisplayGroup displayGroup; // key command to copy contents to clipboard static public final String COPY = "COPY"; protected static final String CLEAR_ALL = "Clear All"; protected static final String CLEAR_SELECTED = "Clear Selected"; /** * Displays all notifications on the default notification center. */ public NotificationInspector() { this(NSNotificationCenter.defaultCenter()); } /** * Displays all notifications from the specified notification center. */ public NotificationInspector(NSNotificationCenter aCenter) { this(aCenter, null, null); } /** * Displays notifications from the default notification center using the * specified name and object filters. */ public NotificationInspector(String notificationName, Object anObject) { this(NSNotificationCenter.defaultCenter(), notificationName, anObject); } /** * Displays notifications on the specified notification center using the * specified name and object filters. */ public NotificationInspector(NSNotificationCenter aCenter, String notificationName, Object anObject) { // show stack traces NSNotification.showStack = true; // register for notifications NSSelector handleNotification = new NSSelector("handleNotification", new Class[] { NSNotification.class }); aCenter.addObserver(this, handleNotification, notificationName, anObject); table = new JTable(); popupMenu = new JPopupMenu(); JMenuItem menuItem = popupMenu.add(CLEAR_SELECTED); menuItem.addActionListener(this); menuItem = popupMenu.add(CLEAR_ALL); menuItem.addActionListener(this); displayGroup = new EODisplayGroup(); TableColumn column; TableColumnAssociation assoc; column = new TableColumn(); column.setHeaderValue("Time"); column.setCellRenderer(new FormattedCellRenderer(new SimpleDateFormat("hh:mm:ss:SS"))); column.setPreferredWidth(90); column.setMaxWidth(90); assoc = new TableColumnAssociation(column); assoc.bindAspect(EOAssociation.ValueAspect, displayGroup, "time"); assoc.setTable(table); assoc.establishConnection(); column = new TableColumn(); column.setHeaderValue("Type"); assoc = new TableColumnAssociation(column); assoc.bindAspect(EOAssociation.ValueAspect, displayGroup, "name"); assoc.setTable(table); assoc.establishConnection(); column = new TableColumn(); column.setHeaderValue("Object"); assoc = new TableColumnAssociation(column); assoc.bindAspect(EOAssociation.ValueAspect, displayGroup, "objectString"); assoc.setTable(table); assoc.establishConnection(); column = new TableColumn(); column.setHeaderValue("Info"); assoc = new TableColumnAssociation(column); assoc.bindAspect(EOAssociation.ValueAspect, displayGroup, "userInfoString"); assoc.setTable(table); assoc.establishConnection(); initLayout(); } protected void initLayout() { table.addMouseListener(this); // listen for double-clicks JPanel panel = new JPanel(); panel.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10))); panel.setLayout(new BorderLayout(10, 10)); JScrollPane scrollPane = new JScrollPane(table); // scrollPane.setPreferredSize( new Dimension( 500, 250 ) ); panel.add(scrollPane, BorderLayout.CENTER); JFrame window = new JFrame(); window.setTitle("Notification Inspector"); window.getContentPane().add(panel); // window.pack(); window.setSize(800, 400); WindowUtilities.cascade(window); // size the columns. // table.getColumnModel().getColumn( 0 ).setPreferredWidth( 100 ); window.show(); } /** * Handles the notification. */ public void handleNotification(NSNotification aNotification) { Surrogate s = new Surrogate(new Object[] { aNotification }); s.directPut("time", new Date()); s.directPut("objectString", "" + aNotification.object()); // snapshot of state s.directPut("userInfoString", "" + aNotification.userInfo()); // snapshot of info displayGroup.insertObjectAtIndex(s, 0); } // interface ActionListener /** * Method used to listen for the action event from the popup menu items. */ public void actionPerformed(ActionEvent e) { if (CLEAR_SELECTED.equals(e.getActionCommand())) { NSMutableArray objects = new NSMutableArray(displayGroup.allObjects()); objects.removeAll(displayGroup.selectedObjects()); displayGroup.setObjectArray(objects); displayGroup.updateDisplayedObjects(); } else if (CLEAR_ALL.equals(e.getActionCommand())) { displayGroup.setObjectArray(null); displayGroup.updateDisplayedObjects(); } } // interface MouseListener /** * Double click to launch object inspector. */ public void mouseClicked(MouseEvent e) { if (e.getSource() == table) { if (e.getClickCount() > 1) { int row = table.rowAtPoint(e.getPoint()); int col = table.columnAtPoint(e.getPoint()); col = table.convertColumnIndexToModel(col); if (row == -1) return; if (col == 0) // time { new StackTraceInspector( ((NSNotification) ((Surrogate) displayGroup.displayedObjects().objectAtIndex(row)) .getDelegate()).stackTrace()); } else if (col == 2) // object { new ObjectInspector( ((NSNotification) ((Surrogate) displayGroup.displayedObjects().objectAtIndex(row)) .getDelegate()).object()); } else if (col == 3) // info { new ObjectInspector( ((NSNotification) ((Surrogate) displayGroup.displayedObjects().objectAtIndex(row)) .getDelegate()).userInfo()); } else { new ObjectInspector(((Surrogate) displayGroup.displayedObjects().objectAtIndex(row)).getDelegate()); } } else { // Click count is 1 then, check for popup trigger. if (e.isPopupTrigger()) { popupMenu.show(table, e.getX(), e.getY()); } } } } public void mouseReleased(MouseEvent e) { if (e.getSource() == table) { if (e.isPopupTrigger() && (e.getClickCount() == 1)) { popupMenu.show(table, e.getX(), e.getY()); } } } public void mousePressed(MouseEvent e) { if (e.getSource() == table) { if (e.isPopupTrigger() && (e.getClickCount() == 1)) { popupMenu.show(table, e.getX(), e.getY()); } } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } } /* * $Log$ Revision 1.2 2006/02/18 23:19:05 cgruber Update imports and maven * dependencies. * * Revision 1.1 2006/02/16 13:22:23 cgruber Check in all sources in * eclipse-friendly maven-enabled packages. * * Revision 1.6 2003/08/06 23:07:52 chochos general code cleanup (mostly, * removing unused imports) * * Revision 1.5 2002/11/18 22:11:51 mpowers rglista's long-overdue enhancements: * can now clear the display! * * Revision 1.4 2002/10/24 18:19:03 mpowers Now telling NSNotification to * generate stack traces. * * Revision 1.3 2001/04/29 22:02:45 mpowers Work on id transposing between * editing contexts. * * Revision 1.2 2001/04/09 21:40:25 mpowers Numerous usability enhancements. * * Revision 1.1 2001/04/08 20:58:45 mpowers Contributing notification inspector. * * */