package com.vistatec.ocelot.tm.gui.match;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import com.vistatec.ocelot.Ocelot;
import com.vistatec.ocelot.tm.TmMatch;
import com.vistatec.ocelot.tm.gui.AbstractDetachableTmPanel;
/**
* This panel implements the Translations match functionality. It is detachable,
* i.e. by pressing the appropriate button the panel is detached from the Ocelot
* main frame and it is displayed inside its own window.
*/
public class TranslationsPanel extends AbstractDetachableTmPanel {
/** The detached component width constant. */
private static final int DETACHED_COMP_WIDTH = 800;
/** The detached component height constant. */
private static final int DETACHED_COMP_HEIGHT = 400;
/** The table displaying matches. */
private TmTable matchesTable;
/** The table data model. */
private TranslationsMatchTableModel tableModel;
/** The scroll panel containing the table. */
private JScrollPane scrollPanel;
private TableCellEditor targetEditor;
/**
* The info panel displayed while loading matches or when the research
* produces no results.
*/
private JPanel infoPanel;
/** The loading label. */
private JLabel lblLoading;
/** Label displayed when no matches are found. */
private JLabel lblNoResults;
/**
* Constructor.
*
* @param controller
* the controller.
*/
public TranslationsPanel(final TmGuiMatchController controller) {
super(controller);
}
/*
* (non-Javadoc)
*
* @see com.vistatec.ocelot.tm.gui.AbstractDetachableTmPanel#makePanel()
*/
@Override
protected void makePanel() {
// Configures the table.
configTable();
// Build the translation results label
JLabel lblTranslations = new JLabel("Translation Results");
lblTranslations.setFont(lblTranslations.getFont().deriveFont(Font.BOLD,
12));
// Build the panel
panel = new JPanel();
panel.setName("Translations");
JPanel translationsPanel = (JPanel) panel;
translationsPanel.setLayout(new GridBagLayout());
GridBagConstraints gridBag = new GridBagConstraints();
// Add the pin button.
gridBag.gridx = 0;
gridBag.gridy = 0;
gridBag.anchor = GridBagConstraints.NORTHWEST;
gridBag.insets = new Insets(10, 5, 10, 0);
translationsPanel.add(getPinComponent(), gridBag);
// Add the translations label.
gridBag.gridx = 1;
gridBag.gridy = 0;
gridBag.anchor = GridBagConstraints.NORTHWEST;
gridBag.insets = new Insets(10, 0, 10, 0);
translationsPanel.add(lblTranslations, gridBag);
// Add the scroll panel containing the table
gridBag.gridx = 0;
gridBag.gridy = 1;
gridBag.gridwidth = 2;
gridBag.weighty = 1;
gridBag.weightx = 1;
gridBag.insets = new Insets(0, 0, 0, 0);
gridBag.fill = GridBagConstraints.BOTH;
gridBag.anchor = GridBagConstraints.NORTH;
scrollPanel = new JScrollPane();
translationsPanel.add(scrollPanel, gridBag);
// Configure info panel and its labels.
lblLoading = new JLabel("Loading...");
lblNoResults = new JLabel("No results");
infoPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
}
/**
* Configures the table.
*/
private void configTable() {
// Create the data model.
tableModel = new TranslationsMatchTableModel(null);
// Create and configure the table.
matchesTable = new TmTable();
matchesTable.setModel(tableModel);
// Make the table react to the ALT+R keystroke.
matchesTable.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_R, Ocelot.getPlatformKeyMask() ),
"replaceTarget");
matchesTable.getActionMap().put("replaceTarget",
new ReplaceTargetAction());
// Set size to the segment number column.
TableColumn numCol = matchesTable.getColumnModel().getColumn(
tableModel.getSegmentNumColumnIdx());
numCol.setPreferredWidth(50);
numCol.setMaxWidth(50);
// Set appropriate renderer to the match score column and set size
TableColumn scoreCol = matchesTable.getColumnModel().getColumn(
tableModel.getMatchScoreColumnIdx());
scoreCol.setCellRenderer(new MatchScoreRenderer());
scoreCol.setPreferredWidth(50);
scoreCol.setMaxWidth(50);
TableColumn targetCol = matchesTable.getColumnModel().getColumn(tableModel.getTargetColumnIdx());
targetEditor = new ReadOnlyCellEditor();
targetCol.setCellEditor(targetEditor);
}
/*
* (non-Javadoc)
*
* @see com.vistatec.ocelot.tm.gui.AbstractDetachableTmPanel#makeWindow()
*/
@Override
protected void makeWindow() {
window = new JFrame();
((JFrame) window).setTitle("Traslation Results");
window.setPreferredSize(new Dimension(DETACHED_COMP_WIDTH,
DETACHED_COMP_HEIGHT));
}
/**
* This class implements the "Replace Target" action. The target of the
* segment currently selected in the main grid is replaced by the target of
* the selected match in the translation panel.
*/
public class ReplaceTargetAction extends AbstractAction {
/** The serial version UID. */
private static final long serialVersionUID = 7013423666969632441L;
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
@Override
public void actionPerformed(ActionEvent e) {
final int selRow = matchesTable.getSelectedRow();
if (selRow != -1) {
TmMatch selMatch = tableModel.getElementAtRow(selRow);
controller.replaceTarget(selMatch.getTarget());
}
}
}
/**
* Sets the panel in loading mode, by displaying the info panel.
*/
public void setLoading() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scrollPanel.setViewportView(infoPanel);
infoPanel.add(lblLoading);
scrollPanel.repaint();
}
});
}
/**
* Displays the translation match results if any; otherwise it displays the
* info panel with "No Results" label.
*
* @param matches
* the translation matches.
*/
public void setTranslationSearchResults(final List<TmMatch> matches) {
if (matches != null && !matches.isEmpty()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
targetEditor.stopCellEditing();
tableModel.setModel(matches);
scrollPanel.setViewportView(matchesTable);
scrollPanel.repaint();
matchesTable.getSelectionModel().setSelectionInterval(0, 0);
}
});
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
targetEditor.stopCellEditing();
infoPanel.removeAll();
infoPanel.add(lblNoResults);
infoPanel.repaint();
}
});
}
}
}