/*
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.
*
*
*/