Log in Help
Print
Homereleasesgate-8.4-build5748-ALLpluginsAlignmentsrcgatealignmentguiviews 〉 MatrixView.java
 
package gate.alignment.gui.views;

import gate.Annotation;
import gate.Document;
import gate.alignment.AlignmentListener;
import gate.alignment.gui.AlignmentAction;
import gate.alignment.gui.AlignmentTask;
import gate.alignment.gui.AlignmentView;
import gate.alignment.gui.PUAPair;
import gate.compound.CompoundDocument;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.MouseInputAdapter;
import javax.swing.table.DefaultTableModel;

/**
 * This class provides an editor for aligning texts in a compound document.
 */
@SuppressWarnings("serial")
public class MatrixView extends JPanel implements AlignmentListener,
                                      AlignmentView {

  private static final long serialVersionUID = -2867467022258265114L;

  /**
   * scrollpane that holds the jtable
   */
  private JScrollPane waScrollPane;

  /**
   * Actual matrix to show data. First column and first row are used for labels.
   */
  private JTable matrix;

  /**
   * Alignment Task object
   */
  private AlignmentTask alignmentTask;

  /**
   * Default font-size
   */
  public static final int TEXT_SIZE = 20;

  private CompoundDocument compoundDocument;

  private AlignmentView thisInstance = null;

  // represents source annotations as shown in rows
  Map<Integer, Annotation> srcAnnotations;

  // represents target annotations as shown in columns
  Map<Integer, Annotation> tgtAnnotations;

  Cell currentCell;

  PUAPair currentPair;

  public MatrixView(AlignmentTask task) {
    srcAnnotations = new HashMap<Integer, Annotation>();
    tgtAnnotations = new HashMap<Integer, Annotation>();
    thisInstance = this;
    setTarget(task);
    initGui();
  }

  /**
   * Initialize the GUI
   */
  private void initGui() {
    setBorder(BorderFactory.createTitledBorder("Matrix View"));
    matrix = new JTable();
    matrix.setColumnSelectionAllowed(false);
    matrix.setTableHeader(null);
    matrix.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    waScrollPane = new JScrollPane(matrix);
    waScrollPane.setColumnHeaderView(null);
    waScrollPane.setPreferredSize(new Dimension(800, 400));
    add(waScrollPane, BorderLayout.CENTER);
    MouseActionListener mal = new MouseActionListener();
    matrix.addMouseListener(mal);
    matrix.addMouseMotionListener(mal);
  }

  public void setTarget(AlignmentTask alignmentTask) {
    this.alignmentTask = alignmentTask;
    this.compoundDocument = alignmentTask.getCompoundDocument();
    compoundDocument.getAlignmentInformation(
            this.alignmentTask.getUaFeatureName()).addAlignmentListener(this);
  }

  /**
   * This method clears up the latest annotation selection
   */
  public void clearLatestAnnotationsSelection() {
    // do nothing - not relevant while using matrix view
  }

  /**
   * Executes the given action. It uses the pair that is being currently shown
   * to collect the alignment information which is then used as parameters to
   * call the provided action.
   * 
   * @param aa
   */
  public void executeAction(AlignmentAction aa) {

    // obtaining selected annotations
    Set<Annotation> srcSelectedAnnots = new HashSet<Annotation>();
    Set<Annotation> tgtSelectedAnnots = new HashSet<Annotation>();

    tgtSelectedAnnots.add(tgtAnnotations.get(currentCell.column));
    srcSelectedAnnots.add(srcAnnotations.get(currentCell.row));

    alignmentTask.getAlignmentActionsManager().executeAction(this, aa,
            srcSelectedAnnots, tgtSelectedAnnots,
            srcAnnotations.get(currentCell.row));
  }

  /**
   * This method updates the GUI.
   * 
   * @param docIDsAndAnnots
   */
  public void updateGUI(PUAPair pair) {
    this.currentPair = pair;
    // before refreshing, we remove all the highlights
    clearLatestAnnotationsSelection();
    srcAnnotations.clear();
    tgtAnnotations.clear();
    int counter = 1;
    for(Annotation a : pair.getSourceUnitAnnotations()) {
      srcAnnotations.put(counter, a);
      counter++;
    }

    counter = 1;
    for(Annotation a : pair.getTargetUnitAnnotations()) {
      tgtAnnotations.put(counter, a);
      counter++;
    }

    matrix.setModel(new AlignmentTableModel(srcAnnotations, tgtAnnotations));
    matrix.updateUI();
  }

  /**
   * listens to the annotationsAligned event and updates the GUI accordingly.
   */
  public void annotationsAligned(Annotation srcAnnotation, String srcAS,
          Document srcDocument, Annotation tgtAnnotation, String tgtAS,
          Document tgtDocument) {
    matrix.updateUI();
  }

  /**
   * listens to the annotationsUnAligned event and updates the GUI accordingly.
   */

  public void annotationsUnaligned(Annotation srcAnnotation, String srcAS,
          Document srcDocument, Annotation tgtAnnotation, String tgtAS,
          Document tgtDocument) {

    matrix.updateUI();
  }

  /**
   * Implements various mouse events. E.g. what should happen when someone
   * clicks on an unhighlighted annotation etc.
   * 
   * @author niraj
   */
  protected class MouseActionListener extends MouseInputAdapter {

    public void mouseClicked(MouseEvent me) {
      mouseExited(me);
      Point p = me.getPoint();
      int row = matrix.rowAtPoint(p);
      int column = matrix.columnAtPoint(p);
      if(row == 0 || column == 0) return;
      Annotation srcAnnot = srcAnnotations.get(row);
      Annotation tgtAnnot = tgtAnnotations.get(column);
      currentCell = new Cell(column, row);
      boolean alignedAnnots =
              alignmentTask.getAlignment().areTheyAligned(srcAnnot, tgtAnnot);

      // we should show the option menu here
      JPopupMenu optionsMenu =
              alignmentTask.getAlignmentActionsManager().prepareOptionsMenu(
                      thisInstance, alignedAnnots, true);
      optionsMenu.show(matrix, (int)p.getX(), (int)p.getY());
      optionsMenu.setVisible(true);
      return;
    }

    JPopupMenu menu = new JPopupMenu();

    FeaturesModel model = new FeaturesModel();

    JTable featuresTable = new JTable(model);

    Timer timer = new Timer();

    TimerTask task;

    public void mouseEntered(final MouseEvent me) {
      mouseExited(me);
      Point p = me.getPoint();
      int row = matrix.rowAtPoint(p);
      int column = matrix.columnAtPoint(p);
      currentCell = new Cell(column, row);

      Annotation a = null;
      if(row == 0) {
        a = tgtAnnotations.get(column);
      } else if(column == 0) {
        a = srcAnnotations.get(row);
      } else {
        return;
      }

      model.setAnnotation(a);
      task = new TimerTask() {
        public void run() {
          menu.add(featuresTable);
          menu.show(matrix, me.getX(), me.getY() + 10);
          menu.revalidate();
          menu.updateUI();
        }
      };
      timer.schedule(task, 2000);
    }

    public void mouseExited(MouseEvent me) {
      if(task != null) {
        task.cancel();
      }
      if(menu != null && menu.isVisible()) {
        menu.setVisible(false);
      }
    }
  }

  /**
   * represents annotation features. This is used for displaying features of the
   * annotation currently being focused by the mouse pointer.
   * 
   * @author gate
   */
  public class FeaturesModel extends DefaultTableModel {

    // annotation whoes features need to be displayed
    Annotation toShow;

    /**
     * keys
     */
    ArrayList<String> features;

    /**
     * values
     */
    ArrayList<String> values;

    /**
     * constructor
     */
    public FeaturesModel() {
      super(new String[]{"Feature", "Value"}, 0);
    }

    /**
     * sets the annotation whoes features need to be shown
     * 
     * @param annot
     */
    public void setAnnotation(Annotation annot) {
      features = new ArrayList<String>();
      values = new ArrayList<String>();
      for(Object key : annot.getFeatures().keySet()) {
        features.add(key.toString());
        values.add(annot.getFeatures().get(key).toString());
      }
      super.fireTableDataChanged();
    }

    public Class<?> getColumnClass(int column) {
      return String.class;
    }

    public int getRowCount() {
      return values == null ? 0 : values.size();
    }

    public int getColumnCount() {
      return 2;
    }

    public String getColumnName(int column) {
      switch(column){
        case 0:
          return "Feature";
        default:
          return "Value";
      }
    }

    public Object getValueAt(int row, int column) {
      switch(column){
        case 0:
          return features.get(row);
        default:
          return values.get(row);
      }
    }

  }

  /**
   * @author gate
   */
  public class AlignmentTableModel extends DefaultTableModel {

    Map<Integer, Annotation> srcAnns = new HashMap<Integer, Annotation>();
    Map<Integer, Annotation> tgtAnns = new HashMap<Integer, Annotation>();

    public AlignmentTableModel(Map<Integer, Annotation> srcAnnots,
            Map<Integer, Annotation> tgtAnnots) {
      this.srcAnns = srcAnnots;
      this.tgtAnns = tgtAnnots;
    }

    
    public int getRowCount() {
      return srcAnns == null ? 0 : srcAnns.size() + 1;
    }

    public int getColumnCount() {
      return tgtAnns == null ? 0 : tgtAnns.size() + 1;
    }

    public Object getValueAt(int row, int col) {
      if((row == 0 && col == 0) || (currentPair == null)) { return ""; }

      if(row == 0) { return currentPair.getText(tgtAnns.get(col), false); }

      if(col == 0) { return currentPair.getText(srcAnns.get(row), true); }

      Annotation srcAnnot = srcAnns.get(row);
      Annotation tgtAnnot = tgtAnns.get(col);
      if(alignmentTask.getAlignment().areTheyAligned(srcAnnot,  tgtAnnot)) {
        return "*";
      } else {
        return "";
      }
    }
  }

  class Cell {
    // column number
    int column;

    // row number
    int row;

    public Cell(int column, int row) {
      super();
      this.column = column;
      this.row = row;
    }
  } // Cell

}