/*******************************************************************************
* Copyright (c) 2008 Jerome Negre.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl-3.0-standalone.html
*
* Contributors:
* Jerome Negre - initial API and implementation
******************************************************************************/
package org.jnegre.redpill.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.Timer;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import org.jnegre.redpill.ContentTypeHelper;
import org.jnegre.redpill.HttpRequest;
import org.jnegre.redpill.HttpResponse;
import org.jnegre.redpill.ServiceProvider;
import org.jnegre.redpill.Session;
import org.jnegre.redpill.SessionManager;
import org.jnegre.redpill.images.ImageProvider;
public class MainDialog extends JFrame {
private final static String[] columnNames = {"", "ID", "Status", "Method", "Host", "Resource"};
private final static int[] columnWidths = {20, 55 , 55 , 55 , 200 , 700};
private final SessionManager sm;
private List<RequestViewer> requestViewers = new ArrayList<RequestViewer>();
private List<ResponseViewer> responseViewers = new ArrayList<ResponseViewer>();
public MainDialog(SessionManager sm) {
super("RedPill");
this.sm = sm;
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setIconImage(ImageProvider.getImage("pill"));
JSplitPane requestResponseSplit = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
createRequestComponent(),
createResponseComponent());
requestResponseSplit.setResizeWeight(0.5);
JSplitPane split = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
new JScrollPane(createSessionTable()),
requestResponseSplit);
split.setResizeWeight(0.5);
add(split, BorderLayout.CENTER);
//add(createToolBar(), BorderLayout.NORTH);
add(createStatusBar(), BorderLayout.SOUTH);
setSize(new Dimension(900,700));
//pack();
}
private Component createSessionTable() {
final DefaultTableModel model = new DefaultTableModel(columnNames,0){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if(columnIndex == 0) {
return ImageIcon.class;
} else {
return super.getColumnClass(columnIndex);
}
}
};
final JTable table = new JTable(model);
for(int i=0; i<columnWidths.length; i++) {
table.getColumnModel().getColumn(i).setPreferredWidth(columnWidths[i]);
}
sm.addListener(new SessionManager.Listener(){
public void onNewSession(Session s) {
model.addRow(new Object[]{"",s.getId(),"","","",""});
}
public void onRequest(Session s) {
HttpRequest r = s.getRequest();
//method
model.setValueAt(r.getMethod(), s.getId(), 3);
//host
String host = r.getHost();
if(r.getPort()!=80) {
host +=":"+r.getPort();
}
model.setValueAt(host, s.getId(), 4);
//resource
model.setValueAt(r.getRelativeUrl(), s.getId(), 5);
}
public void onResponse(Session s) {
HttpResponse r = s.getResponse();
model.setValueAt(ContentTypeHelper.getImageIcon(r.getHeaders().getHeader("Content-type")), s.getId(), 0);
model.setValueAt(r.getStatusCode(), s.getId(), 2);
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
List<Session> sessions = new ArrayList<Session>();//FIXME useful?
List<HttpRequest> requests = new ArrayList<HttpRequest>();
List<HttpResponse> responses = new ArrayList<HttpResponse>();
for(int i : table.getSelectedRows()) {
Session s = sm.getSession(i);
sessions.add(s);
requests.add(s.getRequest());
responses.add(s.getResponse());
}
for(RequestViewer v: requestViewers) {
v.displayRequests(requests);
}
for(ResponseViewer v: responseViewers) {
v.displayResponses(responses);
}
}
});
return table;
}
private Component createRequestComponent() {
JTabbedPane tabbed = new JTabbedPane();
List<Class<RequestViewer>> viewers = ServiceProvider.getServices(RequestViewer.class);
for(Class<RequestViewer> viewer : viewers) {
try {
RequestViewer instance = viewer.newInstance();
requestViewers.add(instance);
tabbed.add(instance.getTitle(), instance.getComponent());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return tabbed;
}
private Component createResponseComponent() {
JTabbedPane tabbed = new JTabbedPane();
List<Class<ResponseViewer>> viewers = ServiceProvider.getServices(ResponseViewer.class);
for(Class<ResponseViewer> viewer : viewers) {
ResponseViewer instance;
try {
instance = viewer.newInstance();
responseViewers.add(instance);
tabbed.add(instance.getTitle(), instance.getComponent());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return tabbed;
}
private JToolBar createToolBar() {
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.add(createButton("Delete", "cross", false));
toolBar.addSeparator();
toolBar.add(createButton("Show only sessions whith an error status", "error", true));
return toolBar;
}
private AbstractButton createButton(String text, String iconName, boolean toggle) {
AbstractButton button;
if(toggle) {
button = new JToggleButton(ImageProvider.getImageIcon(iconName));
} else {
button = new JButton(ImageProvider.getImageIcon(iconName));
}
button.setToolTipText(text);
return button;
}
private Component createStatusBar() {
JPanel bar = new JPanel(new FlowLayout(FlowLayout.LEFT));
final JTextField memory = new JTextField(15);
memory.setEditable(false);
memory.setHorizontalAlignment(JTextField.TRAILING);
bar.add(memory);
Timer timer = new Timer(1000, new ActionListener(){
private String memoryToNiceString(long m) {
String[] units = {" B", " KB", " MB", " GB", " TB", " PB", " EB"}; //should be enough
int u = 0;
for(u=0;u<units.length && m>2048;u++) {
m /=1024;
}
return m+units[u];
}
public void actionPerformed(ActionEvent e) {
Runtime runtime = Runtime.getRuntime();
long total = runtime.totalMemory();
long used = total - runtime.freeMemory();
memory.setText(memoryToNiceString(used)+" / "+memoryToNiceString(total));
memory.setToolTipText((used*100/total)+"% used");
}
});
timer.setInitialDelay(0);
timer.start();
return bar;
}
}