package edu.cmu.minorthird.text.gui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.Iterator;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JTextField;
import edu.cmu.minorthird.text.MutableTextLabels;
import edu.cmu.minorthird.text.Span;
import edu.cmu.minorthird.text.TextLabels;
/**
* Interactivly edit document spans.
*
* @author William Cohen
*/
public class SpanLabeler extends ViewerTracker{
static final long serialVersionUID=200803014L;
// private static final String EDITOR_PROP=SpanEditor.EDITOR_PROP;
// map top-level spans to type that labels them
private static final String LABEL_PROP="userLabel";
private static final String NULL_TYPE="- pick label -";
private static final String UNKNOWN_TYPE="- unknown -";
// internal state
// private String labelType=UNKNOWN_TYPE;
// buttons
final JLabel currentTypeLabel=new JLabel(UNKNOWN_TYPE);
final JComboBox typeBox=new LabelChooserBox();
final JButton addCurrentTypeButton=
new JButton(new AddCurrentTypeAction("Accept class:"));
final JTextField newTypeField=new JTextField(15);
final JButton addNewTypeButton=
new JButton(new AddNewTypeAction("New class:"));
/**
* @param viewLabels
* a superset of editLabels which may include some additional
* read-only information
* @param editLabels
* the labels being modified
* @param documentList
* the document Span being edited is associated with the selected
* entry of the documentList.
* @param spanPainter
* used to repaint documentList elements
* @param statusMsg
* a JLabel used for status messages.
*/
public SpanLabeler(TextLabels viewLabels,MutableTextLabels editLabels,
JList documentList,SpanPainter spanPainter,StatusMessage statusMsg){
super(viewLabels,editLabels,documentList,spanPainter,statusMsg);
setViewEntireDocument(true);
newTypeField.addActionListener(addNewTypeButton.getAction());
restoreLabelProps();
//
// layout stuff
//
setLayout(new GridBagLayout());
GridBagConstraints gbc;
int col=0;
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=2.0;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(currentTypeLabel,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(addCurrentTypeButton,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(typeBox,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(addNewTypeButton,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(newTypeField,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(upButton,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(downButton,gbc);
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.weightx=0.5;
gbc.weighty=0.0;
gbc.gridx=++col;
gbc.gridy=2;
add(saveButton,gbc);
// saveButton.setEnabled( saveAsFile!=null );
gbc=new GridBagConstraints();
gbc.fill=GridBagConstraints.BOTH;
gbc.weightx=1.0;
gbc.weighty=1.0;
gbc.gridx=1;
gbc.gridy=1;
gbc.gridwidth=col;
add(editorHolder,gbc);
loadSpan(nullSpan());
}
// if documentSpan s has type t, then setProperty(s,LABEL_PROP,t)
private void restoreLabelProps(){
// System.out.println("restoring label properties");
for(Iterator<Span> i=editLabels.getTextBase().documentSpanIterator();i
.hasNext();){
Span s=i.next();
for(Iterator<String> j=editLabels.getTypes().iterator();j.hasNext();){
String t=j.next();
if(editLabels.hasType(s,t)){
// System.out.println("restoring "+t+" for "+s);
editLabels.setProperty(s,LABEL_PROP,t);
}
}
}
}
@Override
protected void loadSpanHook(){
String oldLabel=editLabels.getProperty(documentSpan,LABEL_PROP);
if(oldLabel==null){
currentTypeLabel.setText(UNKNOWN_TYPE);
}else{
currentTypeLabel.setText(oldLabel);
}
}
/** Say where the viewer is.. */
public void addViewer(TextBaseViewer viewer){
this.viewer=viewer;
}
private TextBaseViewer viewer=null;
private class AddNewTypeAction extends AbstractAction{
static final long serialVersionUID=200803014L;
public AddNewTypeAction(String msg){
super(msg);
}
@Override
public void actionPerformed(ActionEvent event){
String type=newTypeField.getText().trim();
if(!editLabels.isType(type)){
typeBox.addItem(type);
if(viewer!=null){
viewer.getGuessBox().addItem(type);
viewer.getTruthBox().addItem(type);
viewer.getDisplayedTypeBox().addItem(type);
}
}
setDocumentType(type);
}
}
private class AddCurrentTypeAction extends AbstractAction{
static final long serialVersionUID=200803014L;
public AddCurrentTypeAction(String msg){
super(msg);
}
@Override
public void actionPerformed(ActionEvent event){
String type=(String)typeBox.getSelectedItem();
if(!NULL_TYPE.equals(type))
setDocumentType(type);
}
}
private class LabelChooserBox extends JComboBox{
static final long serialVersionUID=200803014L;
public LabelChooserBox(){
super();
addItem(NULL_TYPE);
for(Iterator<String> i=editLabels.getTypes().iterator();i.hasNext();){
addItem(i.next());
}
addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent event){
String t=(String)getSelectedItem();
if(!NULL_TYPE.equals(t))
setDocumentType(t);
}
});
}
}
private void setDocumentType(String type){
statusMsg.display("setting type="+type+"for "+documentSpan);
currentTypeLabel.setText(type);
String oldLabel=editLabels.getProperty(documentSpan,LABEL_PROP);
if(oldLabel!=null){
// clear the old label
editLabels.defineTypeInside(oldLabel,documentSpan,Collections.<Span>emptySet().iterator());
}
editLabels.setProperty(documentSpan,LABEL_PROP,type);
editLabels.addToType(documentSpan,type);
editLabels.closeTypeInside(type,documentSpan);
}
}