package edu.cmu.minorthird.util.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter;
import org.apache.log4j.Logger;
import edu.cmu.minorthird.util.IOUtil;
import edu.cmu.minorthird.util.Saveable;
import edu.cmu.minorthird.util.StringUtil;
/**
*
* Top-level container for a Viewer.
*
* @author William cohen
*
*/
public class ViewerFrame extends JFrame{
static final long serialVersionUID=20080517L;
static private Logger log=Logger.getLogger(ViewerFrame.class);
private Viewer myViewer=null;
private String myName=null;
private JMenuItem saveItem=null,zoomItem=null,openItem=null;
private Object content=null;
private ContentWrapper wrapper=null;
// private static class StackFrame{
//
// public Viewer view;
//
// public String name;
//
// public StackFrame(String s,Viewer v){
// this.view=v;
// this.name=s;
// }
// }
public ViewerFrame(String name,Viewer viewer){
super();
addMenu();
setContent(name,viewer);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
private void setContent(String name,Viewer viewer){
this.myName=name;
this.myViewer=viewer;
this.content=myViewer.getSerializableContent();
this.wrapper=new ContentWrapper(content);
viewer.setPreferredSize(new java.awt.Dimension(800,600));
getContentPane().removeAll();
getContentPane().add(viewer,BorderLayout.CENTER);
setTitle(name);
myViewer.revalidate();
zoomItem.setEnabled(myViewer.getSubViewNames().size()>0);
saveItem.setEnabled(wrapper.isSaveable());
openItem.setEnabled(wrapper.isSaveable());
//repaint();
}
private void addMenu(){
// build a menu bar
JMenuBar menuBar=new JMenuBar();
setJMenuBar(menuBar);
JMenu menu=new JMenu("File");
menuBar.add(menu);
openItem=new JMenuItem("Open ...");
menu.add(openItem);
openItem.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ev){
JFileChooser chooser=wrapper.makeFileChooser(wrapper);
int returnVal=chooser.showOpenDialog(ViewerFrame.this);
if(returnVal==JFileChooser.APPROVE_OPTION){
try{
Object obj=wrapper.restore(chooser.getSelectedFile());
if(!(obj instanceof Visible)){
throw new RuntimeException(obj.getClass()+" is not Visible");
}
setContent(obj.getClass().toString(),((Visible)obj).toGUI());
}catch(Exception ex){
JOptionPane.showMessageDialog(ViewerFrame.this,"Error opening "+
chooser.getSelectedFile().getName()+": "+ex,"Open File Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
saveItem=new JMenuItem("Save as ...");
menu.add(saveItem);
saveItem.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ev){
if(wrapper.isSaveable()){
log.debug("Wrapper is saveable");
JFileChooser chooser=wrapper.makeFileChooser(wrapper);
int returnVal=chooser.showSaveDialog(ViewerFrame.this);
if(returnVal==JFileChooser.APPROVE_OPTION){
try{
FileFilter filter=chooser.getFileFilter();
String fmt=filter.getDescription();
String ext=wrapper.getExtensionFor(fmt);
File file0=chooser.getSelectedFile();
File file=
(file0.getName().endsWith(ext))?file0:new File(file0
.getParentFile(),file0.getName()+ext);
wrapper.saveAs(file,filter.getDescription());
}catch(Exception ex){
JOptionPane.showMessageDialog(ViewerFrame.this,"Error saving: "+
ex,"Save File Error",JOptionPane.ERROR_MESSAGE);
}
}
}else{
JOptionPane.showMessageDialog(ViewerFrame.this,"You cannot save "+
content.getClass(),"Error",JOptionPane.ERROR_MESSAGE);
}
}
});
JMenuItem exitItem=new JMenuItem("Close");
menu.add(exitItem);
exitItem.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ev){
ViewerFrame.this.dispose();
}
});
JMenu menu2=new JMenu("Go");
menuBar.add(menu2);
zoomItem=new JMenuItem("Zoom..");
menu2.add(zoomItem);
zoomItem.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent ev){
final JDialog dialog=
new JDialog(ViewerFrame.this,"Subpanes to zoom into",true);
JPanel pane=new JPanel();
dialog.getContentPane().add(pane);
ButtonGroup group=new ButtonGroup();
final JRadioButton[] buttons=
new JRadioButton[myViewer.getSubViewNames().size()];
int k=0;
for(Iterator<String> i=myViewer.getSubViewNames().iterator();i.hasNext();){
String name=i.next();
JRadioButton button=new JRadioButton(name);
pane.add(button);
group.add(button);
buttons[k++]=button;
}
JButton launchButton=new JButton(new AbstractAction("Zoom"){
static final long serialVersionUID=20080517L;
@Override
public void actionPerformed(ActionEvent ev){
for(int i=0;i<buttons.length;i++){
if(buttons[i].isSelected()){
final String name=buttons[i].getText();
final Viewer subview=
myViewer.getNamedSubView(buttons[i].getText());
setContent(myName+" / "+name,subview);
dialog.dispose();
}
}
}
});
pane.add(launchButton);
JButton cancelButton=new JButton(new AbstractAction("Cancel"){
static final long serialVersionUID=20080517L;
@Override
public void actionPerformed(ActionEvent ev){
dialog.dispose();
}
});
pane.add(cancelButton);
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
dialog.pack();
dialog.setLocationRelativeTo(ViewerFrame.this);
dialog.setVisible(true);
}
});
}
public static void main(String[] args){
try{
File file=new File(args[0]);
Object obj=IOUtil.loadSerialized(file);
if(!(obj instanceof Visible)){
System.out.println("Not visible object: "+obj.getClass());
}
new ViewerFrame(args[0],((Visible)obj).toGUI());
}catch(Exception ex){
ex.printStackTrace();
System.out.println("usage: ViewerFrame [serializedVisableObjectFile]");
}
}
private static class ContentWrapper implements Saveable{
private Object obj;
private String[] formats;
public static final String SERIALIZED_FORMAT_NAME="Serialized Java Object";
public static final String SERIALIZED_EXT=".serialized";
public ContentWrapper(Object obj){
this.obj=obj;
int n=0;
if(obj instanceof Serializable){
n=1;
}
if(obj instanceof Saveable){
String[] fs=((Saveable)obj).getFormatNames();
formats=new String[fs.length+n];
for(int i=0;i<fs.length;i++)
formats[i+n]=fs[i];
}else{
formats=new String[n];
}
if(obj instanceof Serializable){
formats[0]=SERIALIZED_FORMAT_NAME;
}
log.debug("ContentWrapper for "+obj.getClass()+" has "+formats.length+
" save format(s): "+StringUtil.toString(formats));
}
public boolean isSaveable(){
return formats.length>0;
}
@Override
public String[] getFormatNames(){
return formats;
}
@Override
public String getExtensionFor(String formatName){
if(formatName.equals(SERIALIZED_FORMAT_NAME))
return SERIALIZED_EXT;
else if(obj instanceof Saveable)
return ((Saveable)obj).getExtensionFor(formatName);
else
return null;
}
public FileFilter getFilter(int i){
final String ext=getExtensionFor(formats[i]);
final String fmt=formats[i];
return new FileFilter(){
@Override
public boolean accept(File f){
return f.isDirectory()||f.getName().endsWith(ext);
}
@Override
public String getDescription(){
return fmt;
}
};
}
@Override
public void saveAs(File file,String formatName) throws IOException{
if(!isSaveable())
throw new IllegalArgumentException("can't save "+obj);
if(SERIALIZED_FORMAT_NAME.equals(formatName))
IOUtil.saveSerialized((Serializable)obj,file);
else
((Saveable)obj).saveAs(file,formatName);
}
@Override
public Object restore(File file) throws IOException{
if(!isSaveable())
throw new IllegalArgumentException("can't restore something like "+obj);
if(file.getName().endsWith(SERIALIZED_EXT)){
return IOUtil.loadSerialized(file);
}else{
return ((Saveable)obj).restore(file);
}
}
public JFileChooser makeFileChooser(ContentWrapper w){
JFileChooser chooser=new JFileChooser();
for(int i=0;i<formats.length;i++){
chooser.addChoosableFileFilter(w.getFilter(i));
}
return chooser;
}
}
}