package com.vistatec.ocelot.freme.gui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import com.vistatec.ocelot.Ocelot;
import com.vistatec.ocelot.segment.model.enrichment.Enrichment;
import com.vistatec.ocelot.segment.model.enrichment.EntityEnrichment;
import com.vistatec.ocelot.segment.model.enrichment.LinkEnrichment;
import com.vistatec.ocelot.segment.model.enrichment.TerminologyEnrichment;
/**
* Panels displaying enrichments details.
*/
public class EnrichmentDetailsPanel extends JScrollPane {
/** The serial version UID. */
private static final long serialVersionUID = 2996737747478539335L;
/** The Entity enrichment icon name. */
private static final String ENTITY_ICON_NAME = "entity";
/** The Terminology enrichment icon name. */
private static final String TERMINOLOGY_ICON_NAME = "term";
/** The Link enrichment icon name. */
private static final String LINK_ICON_NAME = "link";
/** The panel maximum height. */
private static final int MAX_HEIGHT = 250;
/** The panel width. */
private int width;
/** The panel height. */
private int height;
/** The table displaying entities details. */
private JTable entityTable;
/** The table displaying links details. */
private JTable linkTable;
/** The table displaying terms details. */
private JTable termTable;
/** The panel displaying entities details. */
private JPanel entityPanel;
/** The entity enrichments table model. */
private EnrichmentTableModel entityModel;
/** The link enrichments table model. */
private EnrichmentTableModel linkModel;
/** The terminology enrichments table model. */
private EnrichmentTableModel termModel;
/** The panel displaying terminology enrichments details. */
private JPanel terminologyPanel;
/** The panel displaying link enrichments details. */
private JPanel linkPanel;
/** The list of enrichments. */
private List<Enrichment> enrichments;
/** The background color. */
private Color background;
/** The main panel. */
private JPanel mainPanel;
/**
* Constructor.
*
* @param enrichments
* the list of enrichments
* @param background
* the background color.
*/
public EnrichmentDetailsPanel(final List<Enrichment> enrichments,
final Color background) {
this.enrichments = enrichments;
this.background = background;
buildPanel();
}
/**
* Builds the panel.
*/
private void buildPanel() {
if (enrichments != null) {
System.out.println("ENRICHMENTS");
for (Enrichment e : enrichments) {
System.out.println(e.toString());
if (e.getType().equals(Enrichment.ENTITY_TYPE)) {
addToEntityPanel((EntityEnrichment) e);
} else if (e.getType().equals(Enrichment.TERMINOLOGY_TYPE)) {
addToTerminologyPanel((TerminologyEnrichment) e);
} else if (e.getType().equals(Enrichment.LINK_TYPE)) {
addToLinkPanel((LinkEnrichment) e);
}
}
}
final Dimension size = new Dimension(width + 60, height + 50);
mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBackground(background);
configEnrichmentPanel(entityPanel, entityTable, entityModel);
configEnrichmentPanel(linkPanel, linkTable, linkModel);
configEnrichmentPanel(terminologyPanel, termTable, termModel);
setViewportView(mainPanel);
setBorder(BorderFactory.createEmptyBorder());
setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
setSize(size);
setPreferredSize(size);
setBackground(background);
}
/**
* Configures an enrichment panel with its enrichments table and table
* model.
*
* @param enrichPanel
* the enrichment panel
* @param enrichTable
* the enrichment table
* @param model
* the enrichment table model.
*/
private void configEnrichmentPanel(final JPanel enrichPanel,
final JTable enrichTable, final EnrichmentTableModel model) {
if (enrichPanel != null) {
mainPanel.add(enrichPanel);
enrichTable.setSize(width + 50,
enrichTable.getRowHeight() * model.getRowCount());
enrichTable.setPreferredSize(new Dimension(width + 20, enrichTable
.getRowHeight() * model.getRowCount()));
enrichPanel.setSize(enrichTable.getSize());
enrichPanel.setPreferredSize(enrichTable.getSize());
}
}
/**
* Adds an entity enrichment to the entities panel.
*
* @param enrich
* the enrichment to add.
*/
private void addToEntityPanel(EntityEnrichment enrich) {
if (entityPanel == null) {
entityModel = new EnrichmentTableModel(null, true);
entityTable = new JTable(entityModel);
ActionListener entityListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().browse(new URI(btn.getText()));
} catch (IOException ex) { /* TODO: error handling */
ex.printStackTrace();
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
}
};
entityTable
.setDefaultRenderer(String.class, new LinkRenderer(true));
TableColumn column = entityTable.getColumnModel().getColumn(1);
column.setCellEditor(new LinkEditor(entityListener, true));
entityPanel = buildDetailPanel(ENTITY_ICON_NAME, entityTable);
}
entityModel.addEnrichment(enrich);
LinkRenderer renderer = (LinkRenderer) entityTable
.getCellRenderer(0, 1);
JButton renderedComp = (JButton) renderer.getComponent(enrich
.toString());
if (renderedComp.getWidth() > width) {
width = renderedComp.getWidth();
}
}
/**
* Adds a link enrichment to the links panel.
*
* @param enrich
* the link enrichment
*/
private void addToLinkPanel(final LinkEnrichment enrich) {
if (linkPanel == null) {
linkModel = new EnrichmentTableModel(null, true);
linkTable = new JTable(linkModel);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
LinkEnrichmentFrame enrichFrame = new LinkEnrichmentFrame(
enrich,
SwingUtilities
.windowForComponent(EnrichmentDetailsPanel.this));
enrichFrame.open();
}
};
linkTable.setDefaultRenderer(String.class, new LinkRenderer(false));
TableColumn column = linkTable.getColumnModel().getColumn(1);
column.setCellEditor(new LinkEditor(listener, false));
linkPanel = buildDetailPanel(LINK_ICON_NAME, linkTable);
}
linkModel.addEnrichment(enrich);
LinkRenderer renderer = (LinkRenderer) linkTable.getCellRenderer(0, 1);
JButton renderedComp = (JButton) renderer.getComponent(enrich
.toString());
if (renderedComp.getWidth() > width) {
width = renderedComp.getWidth();
}
}
/**
* Builds a details panel.
*
* @param iconPath
* the path of the enrichment icon
* @param table
* the table
* @return the built panel.
*/
private JPanel buildDetailPanel(final String iconPath, final JTable table) {
JPanel panel = new JPanel();
panel.setBackground(background);
table.setBackground(background);
table.setShowGrid(false);
table.setSelectionBackground(background);
panel.add(table);
TableColumn column = table.getColumnModel().getColumn(
EnrichmentTableModel.BUTTON_COL);
column.setCellEditor(new ToggleButtonEditor(iconPath));
column.setCellRenderer(new ToggleButtonRenderer(iconPath));
column.setMaxWidth(25);
column.setWidth(25);
table.setRowHeight(25);
return panel;
}
/**
* Adds a terminology enrichment to the terminologies panel.
*
* @param enrich
* the enrichment.
*/
private void addToTerminologyPanel(final TerminologyEnrichment enrich) {
if (terminologyPanel == null) {
termModel = new EnrichmentTableModel(null, true);
termTable = new JTable(termModel);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int selRow = termTable.getSelectedRow();
if(selRow != -1){
TerminologyEnrichment selEnrichment = (TerminologyEnrichment) termModel.getEnrichmentAtRow(selRow);
TerminologyEnrichmentFrame termFrame = new TerminologyEnrichmentFrame( SwingUtilities
.windowForComponent(EnrichmentDetailsPanel.this), selEnrichment);
termFrame.open();
}
}
};
termTable.setDefaultRenderer(String.class, new LinkRenderer(true));
TableColumn column = termTable.getColumnModel().getColumn(1);
column.setCellEditor(new LinkEditor(listener, true));
terminologyPanel = buildDetailPanel(TERMINOLOGY_ICON_NAME,
termTable);
}
termModel.addEnrichment(enrich);
FontMetrics metrics = terminologyPanel.getFontMetrics(terminologyPanel
.getFont());
computeSize(metrics, enrich.toString());
}
/**
* Gets all the enabled enrichments.
*
* @return the list of enabled enrichments.
*/
public List<Enrichment> getEnabledEnrichments() {
List<Enrichment> enabledEnrichments = new ArrayList<Enrichment>();
if (enrichments != null) {
for (Enrichment e : enrichments) {
if (!e.isDisabled()) {
enabledEnrichments.add(e);
}
}
}
return enabledEnrichments;
}
/**
* Gets all the disabled enrichments.
*
* @return the list of disabled enrichments.
*/
public List<Enrichment> getDisabledEnrichments() {
List<Enrichment> disabledEnrichments = new ArrayList<Enrichment>();
if (enrichments != null) {
for (Enrichment e : enrichments) {
if (e.isDisabled()) {
disabledEnrichments.add(e);
}
}
}
return disabledEnrichments;
}
/**
* Computes the size of the panel.
*
* @param metrics
* the font metrics
* @param enrichString
* the enrichment string
*/
private void computeSize(final FontMetrics metrics,
final String enrichString) {
if (enrichString != null) {
int enrichmentWidth = metrics.charsWidth(
enrichString.toCharArray(), 0, enrichString.length()) + 30;
if (enrichmentWidth > width) {
width = enrichmentWidth;
}
height += metrics.getHeight() + 10;
if (height > MAX_HEIGHT) {
height = MAX_HEIGHT;
}
System.out.println(" Enrichment: " + enrichString + "\n width = "
+ width + " - height = " + height);
}
}
}
/**
* Toggle button used for enabling/disabling the enrichments.
*/
class EnableDisableButton extends JToggleButton {
/** The serial version UID. */
private static final long serialVersionUID = -4691075227280892484L;
/** The enabled icon suffix. */
private static final String ENABLED_ICON_SUFFIX = "-enabled.png";
/** The disabled icon suffix. */
private static final String DISABLED_ICON_SUFFIX = "-disabled.png";
/** The icon displayed when the button is selected. */
private ImageIcon selectedIcon;
/** The icon displayed when the button is not selected. */
private ImageIcon unselectedIcon;
/**
* Constructor.
*
* @param iconPath
* the prefix of the icon file name.
*/
public EnableDisableButton(final String iconPath) {
final Toolkit kit = Toolkit.getDefaultToolkit();
selectedIcon = new ImageIcon(kit.createImage(Ocelot.class
.getResource(iconPath + ENABLED_ICON_SUFFIX)));
unselectedIcon = new ImageIcon(kit.createImage(Ocelot.class
.getResource(iconPath + DISABLED_ICON_SUFFIX)));
setSelectedIcon(selectedIcon);
setIcon(unselectedIcon);
setPreferredSize(new Dimension(20, 20));
setOpaque(false);
setBorderPainted(false);
setContentAreaFilled(false);
}
}
/**
* Renderer for the toggle button used for enabling/disabling enrichments.
*/
class ToggleButtonRenderer extends DefaultTableCellRenderer {
/** The serial version UID. */
private static final long serialVersionUID = -3961708012107549317L;
/** The toggle button. */
private EnableDisableButton button;
/**
* Constructor.
*
* @param iconPath
* the icon name
*/
public ToggleButtonRenderer(final String iconPath) {
button = new EnableDisableButton(iconPath);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
button.setSelected((boolean) value);
button.setBackground(table.getBackground());
return button;
}
}
/**
* Editor for the toggle button used for enabling/disabling enrichments.
*/
class ToggleButtonEditor extends DefaultCellEditor implements ActionListener {
/** The serial version UID. */
private static final long serialVersionUID = 8057060671044058694L;
/** The toggle button. */
private EnableDisableButton button;
/**
* Constructor.
*
* @param iconPath
* the icon name.
*/
public ToggleButtonEditor(final String iconPath) {
super(new JCheckBox());
button = new EnableDisableButton(iconPath);
button.addActionListener(this);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
button.setSelected((boolean) value);
return button;
}
@Override
public Object getCellEditorValue() {
return button.isSelected();
}
@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
}
/**
* Renderer for the link enrichment.
*/
class LinkRenderer extends DefaultTableCellRenderer {
/** The serial version UID. */
private static final long serialVersionUID = 4339337048277285400L;
/**
* States if the value a link enrichment. If it's false, then the value is
* the name of the entity the links are related to.
*/
private boolean link;
/**
* Constructor.
*
* @param link
* a boolean stating if the value of this enrichment is an actual
* link. If it's not a link, then it is the name of the related
* entity.
*/
public LinkRenderer(final boolean link) {
this.link = link;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return getComponent((String) value);
}
/**
* Gets the component rendering this link enrichment.
*
* @param value
* the link value.
* @return the component that renders this link enrichment.
*/
public Component getComponent(String value) {
JButton button = new JButton();
if (link) {
button.setText((String) value);
} else {
button.setText("View info about " + (String) value);
}
button.setHorizontalAlignment(SwingConstants.LEFT);
button.setToolTipText(button.getText());
button.setOpaque(false);
button.setBackground(Color.WHITE);
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
button.setForeground(Color.BLUE);
button.setBorder(BorderFactory.createEmptyBorder());
FontMetrics metrics = button.getFontMetrics(button.getFont());
button.setPreferredSize(new Dimension(metrics.charsWidth(button
.getText().toCharArray(), 0, button.getText().length()) + 30,
button.getHeight()));
button.setSize(new Dimension(metrics.charsWidth(button.getText()
.toCharArray(), 0, button.getText().length()) + 30, button
.getHeight()));
return button;
}
}
/**
* Editor for link enrichments.
*/
class LinkEditor extends DefaultCellEditor {
/** The serial version UID. */
private static final long serialVersionUID = -1290282866909184711L;
/** The action listener. */
private ActionListener listener;
/**
* States if the value a link enrichment. If it's false, then the value is
* the name of the entity the links are related to.
*/
private boolean link;
/**
* Constructor.
*
* @param listener
* the action listener.
* @param link
* a boolean stating if the value of this enrichment is an actual
* link. If it's not a link, then it is the name of the related
* entity.
*/
public LinkEditor(final ActionListener listener, boolean link) {
super(new JCheckBox());
this.listener = listener;
this.link = link;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
JButton button = new JButton();
if (link) {
button.setText((String) value);
} else {
button.setText("View info about " + (String) value);
}
button.setHorizontalAlignment(SwingConstants.LEFT);
button.setToolTipText(button.getText());
button.setOpaque(false);
button.setBackground(Color.WHITE);
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
button.setForeground(Color.BLUE);
button.addActionListener(listener);
button.setBorder(BorderFactory.createEmptyBorder());
FontMetrics metrics = button.getFontMetrics(button.getFont());
button.setPreferredSize(new Dimension(metrics.charsWidth(button
.getText().toCharArray(), 0, button.getText().length()) + 30,
button.getHeight()));
button.setSize(new Dimension(metrics.charsWidth(button.getText()
.toCharArray(), 0, button.getText().length()) + 30, button
.getHeight()));
return button;
}
}