Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
gate.gui.FeaturesSchemaEditor Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2005, The University of Sheffield.
*
* This file is part of GATE (see http://gate.ac.uk/), and is free software,
* licenced under the GNU Library General Public License, Version 2, June 1991
* (in the distribution as file licence.html, and also available at
* http://gate.ac.uk/gate/licence.html).
*
* FeaturesSchemaEditor.java
*
* Valentin Tablan, May 18, 2004
*
* $Id: FeaturesSchemaEditor.java 18884 2015-08-25 17:23:21Z markagreenwood $
*/
package gate.gui;
import gate.Factory;
import gate.FeatureMap;
import gate.Resource;
import gate.creole.AbstractResource;
import gate.creole.AnnotationSchema;
import gate.creole.FeatureSchema;
import gate.creole.ResourceInstantiationException;
import gate.creole.metadata.CreoleResource;
import gate.creole.metadata.GuiType;
import gate.event.FeatureMapListener;
import gate.swing.XJTable;
import gate.util.FeatureBearer;
import gate.util.GateRuntimeException;
import gate.util.ObjectComparator;
import gate.util.Strings;
import java.awt.AWTKeyStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
/**
*/
@SuppressWarnings({"serial","rawtypes","unchecked"})
@CreoleResource(name = "Resource Features", guiType = GuiType.SMALL,
resourceDisplayed = "gate.util.FeatureBearer")
public class FeaturesSchemaEditor extends XJTable
implements ResizableVisualResource, FeatureMapListener{
public FeaturesSchemaEditor(){
// setBackground(UIManager.getDefaults().getColor("Table.background"));
instance = this;
}
public void setTargetFeatures(FeatureMap features){
if(targetFeatures != null) targetFeatures.removeFeatureMapListener(this);
this.targetFeatures = features;
populate();
if(targetFeatures != null) targetFeatures.addFeatureMapListener(this);
}
@Override
public void cleanup() {
if(targetFeatures != null){
targetFeatures.removeFeatureMapListener(this);
targetFeatures = null;
}
target = null;
schema = null;
}
/* (non-Javadoc)
* @see gate.VisualResource#setTarget(java.lang.Object)
*/
@Override
public void setTarget(Object target){
this.target = (FeatureBearer)target;
setTargetFeatures(this.target.getFeatures());
}
public void setSchema(AnnotationSchema schema){
this.schema = schema;
featuresModel.fireTableRowsUpdated(0, featureList.size() - 1);
}
/* (non-Javadoc)
* @see gate.event.FeatureMapListener#featureMapUpdated()
* Called each time targetFeatures is changed.
*/
@Override
public void featureMapUpdated(){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
populate();
}
});
}
/** Initialise this resource, and return it. */
@Override
public Resource init() throws ResourceInstantiationException {
featureList = new ArrayList();
emptyFeature = new Feature("", null);
featureList.add(emptyFeature);
initGUI();
return this;
}//init()
protected void initGUI(){
featuresModel = new FeaturesTableModel();
setModel(featuresModel);
setTableHeader(null);
setSortable(false);
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
setShowGrid(false);
setBackground(getBackground());
setIntercellSpacing(new Dimension(2,2));
setTabSkipUneditableCell(true);
setEditCellAsSoonAsFocus(true);
featureEditorRenderer = new FeatureEditorRenderer();
getColumnModel().getColumn(ICON_COL).
setCellRenderer(featureEditorRenderer);
getColumnModel().getColumn(NAME_COL).
setCellRenderer(featureEditorRenderer);
getColumnModel().getColumn(NAME_COL).
setCellEditor(featureEditorRenderer);
getColumnModel().getColumn(VALUE_COL).
setCellRenderer(featureEditorRenderer);
getColumnModel().getColumn(VALUE_COL).
setCellEditor(featureEditorRenderer);
getColumnModel().getColumn(DELETE_COL).
setCellRenderer(featureEditorRenderer);
getColumnModel().getColumn(DELETE_COL).
setCellEditor(featureEditorRenderer);
// //the background colour seems to change somewhere when using the GTK+
// //look and feel on Linux, so we copy the value now and set it
// Color tableBG = getBackground();
// //make a copy of the value (as the reference gets changed somewhere)
// tableBG = new Color(tableBG.getRGB());
// setBackground(tableBG);
// allow Tab key to select the next cell in the table
setSurrendersFocusOnKeystroke(true);
setFocusCycleRoot(true);
// remove (shift) control tab as traversal keys
Set keySet = new HashSet(
getFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
keySet.remove(KeyStroke.getKeyStroke("control TAB"));
setFocusTraversalKeys(
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keySet);
keySet = new HashSet(
getFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
keySet.remove(KeyStroke.getKeyStroke("shift control TAB"));
setFocusTraversalKeys(
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keySet);
// add (shift) control tab to go the container of this component
keySet.clear();
keySet.add(KeyStroke.getKeyStroke("control TAB"));
setFocusTraversalKeys(
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, keySet);
keySet.clear();
keySet.add(KeyStroke.getKeyStroke("shift control TAB"));
setFocusTraversalKeys(
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, keySet);
}
/**
* Called internally whenever the data represented changes.
* Get feature names from targetFeatures and schema then sort them
* and add them to featureList.
* Fire a table data changed event for the feature table whith featureList
* used as data model.
*/
protected void populate(){
featureList.clear();
//get all the existing features
Set fNames = new HashSet();
if(targetFeatures != null){
//add all the schema features
fNames.addAll(targetFeatures.keySet());
if(schema != null && schema.getFeatureSchemaSet() != null){
for(FeatureSchema featureSchema : schema.getFeatureSchemaSet()) {
// if(featureSchema.isRequired())
fNames.add(featureSchema.getFeatureName());
}
}
List featureNames = new ArrayList(fNames);
Collections.sort(featureNames);
for(Object featureName : featureNames) {
String name = (String) featureName;
Object value = targetFeatures.get(name);
featureList.add(new Feature(name, value));
}
}
if (!featureList.contains(emptyFeature)) {
featureList.add(emptyFeature);
}
featuresModel.fireTableDataChanged();
// mainTable.setSize(mainTable.getPreferredScrollableViewportSize());
}
FeatureMap targetFeatures;
FeatureBearer target;
Feature emptyFeature;
AnnotationSchema schema;
FeaturesTableModel featuresModel;
List featureList;
FeatureEditorRenderer featureEditorRenderer;
FeaturesSchemaEditor instance;
private static final int COLUMNS = 4;
private static final int ICON_COL = 0;
private static final int NAME_COL = 1;
private static final int VALUE_COL = 2;
private static final int DELETE_COL = 3;
private static final Color REQUIRED_WRONG = Color.RED;
private static final Color OPTIONAL_WRONG = Color.ORANGE;
protected class Feature{
String name;
Object value;
public Feature(String name, Object value){
this.name = name;
this.value = value;
}
boolean isSchemaFeature(){
return schema != null && schema.getFeatureSchema(name) != null;
}
boolean isCorrect(){
if(schema == null) return true;
FeatureSchema fSchema = schema.getFeatureSchema(name);
return fSchema == null || fSchema.getPermittedValues() == null||
fSchema.getPermittedValues().contains(value);
}
boolean isRequired(){
if(schema == null) return false;
FeatureSchema fSchema = schema.getFeatureSchema(name);
return fSchema != null && fSchema.isRequired();
}
Object getDefaultValue(){
if(schema == null) return null;
FeatureSchema fSchema = schema.getFeatureSchema(name);
return fSchema == null ? null : fSchema.getFeatureValue();
}
}
protected class FeaturesTableModel extends AbstractTableModel{
@Override
public int getRowCount(){
return featureList.size();
}
@Override
public int getColumnCount(){
return COLUMNS;
}
@Override
public Object getValueAt(int row, int column){
Feature feature = featureList.get(row);
switch(column){
case NAME_COL:
return feature.name;
case VALUE_COL:
return feature.value;
default:
return null;
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex){
return columnIndex == VALUE_COL || columnIndex == NAME_COL ||
columnIndex == DELETE_COL;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
Feature feature = featureList.get(rowIndex);
if (feature == null) { return; }
if(targetFeatures == null){
targetFeatures = Factory.newFeatureMap();
target.setFeatures(targetFeatures);
setTargetFeatures(targetFeatures);
}
switch(columnIndex){
case VALUE_COL:
if (feature.value != null
&& feature.value.equals(aValue)) { return; }
feature.value = aValue;
if(feature.name != null && feature.name.length() > 0){
targetFeatures.removeFeatureMapListener(instance);
targetFeatures.put(feature.name, aValue);
targetFeatures.addFeatureMapListener(instance);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// edit the last row that is empty
FeaturesSchemaEditor.this.editCellAt(FeaturesSchemaEditor.this.getRowCount() - 1, NAME_COL);
}
});
}
break;
case NAME_COL:
if (feature.name.equals(aValue)) {
return;
}
targetFeatures.remove(feature.name);
feature.name = (String)aValue;
targetFeatures.put(feature.name, feature.value);
if(feature == emptyFeature) emptyFeature = new Feature("", null);
populate();
int newRow;
for (newRow = 0; newRow < FeaturesSchemaEditor.this.getRowCount(); newRow++) {
if (FeaturesSchemaEditor.this.getValueAt(newRow, NAME_COL).equals(feature.name)) {
break; // find the previously selected row in the new table
}
}
final int newRowF = newRow;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// edit the cell containing the value associated with this name
FeaturesSchemaEditor.this.editCellAt(newRowF, VALUE_COL);
}
});
break;
case DELETE_COL:
//nothing
break;
default:
throw new GateRuntimeException("Non editable cell!");
}
}
@Override
public String getColumnName(int column){
switch(column){
case NAME_COL:
return "Name";
case VALUE_COL:
return "Value";
case DELETE_COL:
return "";
default:
return null;
}
}
}
protected class FeatureEditorRenderer extends DefaultCellEditor
implements TableCellRenderer {
@Override
public boolean stopCellEditing() {
// this is a fix for a bug in Java 8 where tabbing out of the
// combo box doesn't store the value like it does in java 7
editorCombo.setSelectedItem(editorCombo.getEditor().getItem());
return super.stopCellEditing();
}
public FeatureEditorRenderer(){
super(new JComboBox());
defaultComparator = new ObjectComparator();
editorCombo = (JComboBox)editorComponent;
editorCombo.setModel(new DefaultComboBoxModel());
editorCombo.setEditable(true);
editorCombo.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent evt){
stopCellEditing();
}
});
defaultBackground = editorCombo.getEditor().getEditorComponent()
.getBackground();
rendererCombo = new JComboBox(){
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
rendererCombo.setModel(new DefaultComboBoxModel());
rendererCombo.setEditable(true);
rendererCombo.setOpaque(false);
requiredIconLabel = new JLabel(){
@Override
public void repaint(long tm, int x, int y, int width, int height){}
@Override
public void repaint(Rectangle r){}
@Override
public void validate(){}
@Override
public void revalidate(){}
@Override
protected void firePropertyChange(String propertyName,
Object oldValue,
Object newValue){}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
requiredIconLabel.setIcon(MainFrame.getIcon("r"));
requiredIconLabel.setOpaque(false);
requiredIconLabel.setToolTipText("Required feature");
optionalIconLabel = new JLabel(){
@Override
public void repaint(long tm, int x, int y, int width, int height){}
@Override
public void repaint(Rectangle r){}
@Override
public void validate(){}
@Override
public void revalidate(){}
@Override
protected void firePropertyChange(String propertyName,
Object oldValue,
Object newValue){}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
optionalIconLabel.setIcon(MainFrame.getIcon("o"));
optionalIconLabel.setOpaque(false);
optionalIconLabel.setToolTipText("Optional feature");
nonSchemaIconLabel = new JLabel(MainFrame.getIcon("c")){
@Override
public void repaint(long tm, int x, int y, int width, int height){}
@Override
public void repaint(Rectangle r){}
@Override
public void validate(){}
@Override
public void revalidate(){}
@Override
protected void firePropertyChange(String propertyName,
Object oldValue,
Object newValue){}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
};
nonSchemaIconLabel.setToolTipText("Custom feature");
nonSchemaIconLabel.setOpaque(false);
deleteButton = new JButton(MainFrame.getIcon("delete"));
deleteButton.setMargin(new Insets(0,0,0,0));
deleteButton.setToolTipText("Delete");
deleteButton.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent evt){
int row = FeaturesSchemaEditor.this.getEditingRow();
if(row < 0) return;
Feature feature = featureList.get(row);
if(feature == emptyFeature){
feature.value = null;
}else{
featureList.remove(row);
targetFeatures.remove(feature.name);
featuresModel.fireTableRowsDeleted(row, row);
// mainTable.setSize(mainTable.getPreferredScrollableViewportSize());
}
}
});
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column){
Feature feature = featureList.get(row);
switch(column){
case ICON_COL:
return feature.isSchemaFeature() ?
(feature.isRequired() ?
requiredIconLabel :
optionalIconLabel) :
nonSchemaIconLabel;
case NAME_COL:
prepareCombo(rendererCombo, row, column);
rendererCombo.getPreferredSize();
return rendererCombo;
case VALUE_COL:
prepareCombo(rendererCombo, row, column);
return rendererCombo;
case DELETE_COL: return deleteButton;
default: return null;
}
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column){
switch(column){
case NAME_COL:
prepareCombo(editorCombo, row, column);
return editorCombo;
case VALUE_COL:
prepareCombo(editorCombo, row, column);
return editorCombo;
case DELETE_COL: return deleteButton;
default: return null;
}
}
protected void prepareCombo(JComboBox combo, int row, int column){
Feature feature = featureList.get(row);
DefaultComboBoxModel comboModel = (DefaultComboBoxModel)combo.getModel();
comboModel.removeAllElements();
switch(column){
case NAME_COL:
List fNames = new ArrayList();
if(schema != null && schema.getFeatureSchemaSet() != null){
Iterator fSchemaIter = schema.getFeatureSchemaSet().iterator();
while(fSchemaIter.hasNext())
fNames.add(fSchemaIter.next().getFeatureName());
}
if(!fNames.contains(feature.name))fNames.add(feature.name);
Collections.sort(fNames);
for(Iterator nameIter = fNames.iterator();
nameIter.hasNext();
comboModel.addElement(nameIter.next()));
combo.getEditor().getEditorComponent().setBackground(defaultBackground);
combo.setSelectedItem(feature.name);
break;
case VALUE_COL:
List fValues = new ArrayList();
if(feature.isSchemaFeature()){
Set permValues = schema.getFeatureSchema(feature.name).
getPermittedValues();
if(permValues != null) fValues.addAll(permValues);
}
if(!fValues.contains(feature.value)) fValues.add(feature.value);
Collections.sort(fValues, defaultComparator);
for(Iterator valIter = fValues.iterator();
valIter.hasNext();
comboModel.addElement(valIter.next()));
combo.getEditor().getEditorComponent().setBackground(feature.isCorrect() ?
defaultBackground :
(feature.isRequired() ? REQUIRED_WRONG : OPTIONAL_WRONG));
combo.setSelectedItem(feature.value);
break;
default: ;
}
}
JLabel requiredIconLabel;
JLabel optionalIconLabel;
JLabel nonSchemaIconLabel;
JComboBox editorCombo;
JComboBox rendererCombo;
JButton deleteButton;
ObjectComparator defaultComparator;
Color defaultBackground;
}
/*
* Resource implementation
*/
/** Accessor for features. */
@Override
public FeatureMap getFeatures(){
return features;
}//getFeatures()
/** Mutator for features*/
@Override
public void setFeatures(FeatureMap features){
this.features = features;
}// setFeatures()
/**
* Used by the main GUI to tell this VR what handle created it. The VRs can
* use this information e.g. to add items to the popup for the resource.
*/
@Override
public void setHandle(Handle handle){
this.handle = handle;
}
//Parameters utility methods
/**
* Gets the value of a parameter of this resource.
* @param paramaterName the name of the parameter
* @return the current value of the parameter
*/
@Override
public Object getParameterValue(String paramaterName)
throws ResourceInstantiationException{
return AbstractResource.getParameterValue(this, paramaterName);
}
/**
* Sets the value for a specified parameter.
*
* @param paramaterName the name for the parameteer
* @param parameterValue the value the parameter will receive
*/
@Override
public void setParameterValue(String paramaterName, Object parameterValue)
throws ResourceInstantiationException{
// get the beaninfo for the resource bean, excluding data about Object
BeanInfo resBeanInf = null;
try {
resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class);
} catch(Exception e) {
throw new ResourceInstantiationException(
"Couldn't get bean info for resource " + this.getClass().getName()
+ Strings.getNl() + "Introspector exception was: " + e
);
}
AbstractResource.setParameterValue(this, resBeanInf, paramaterName, parameterValue);
}
/**
* Sets the values for more parameters in one step.
*
* @param parameters a feature map that has paramete names as keys and
* parameter values as values.
*/
@Override
public void setParameterValues(FeatureMap parameters)
throws ResourceInstantiationException{
AbstractResource.setParameterValues(this, parameters);
}
// Properties for the resource
protected FeatureMap features;
/**
* The handle for this visual resource
*/
protected Handle handle;
}