package jav.gui.error;
import jav.correctionBackend.OCRErrorInfo;
import jav.gui.cookies.FontZoomCookie;
import jav.gui.events.MessageCenter;
import jav.gui.events.documentChanged.DocumentChangedEvent;
import jav.gui.events.documentChanged.DocumentChangedEventSlot;
import jav.gui.events.tokenStatus.CorrectedEvent;
import jav.gui.events.tokenStatus.TokenStatusEvent;
import jav.gui.events.tokenStatus.TokenStatusEventSlot;
import jav.gui.events.tokenStatus.TokenStatusType;
import jav.gui.main.AbstractMyTopComponent;
import jav.gui.main.MainController;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
import org.openide.windows.IOProvider;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
*Copyright (c) 2012, IMPACT working group at the Centrum für Informations- und Sprachverarbeitung, University of Munich.
*All rights reserved.
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are met:
*Redistributions of source code must retain the above copyright
*notice, this list of conditions and the following disclaimer.
*Redistributions in binary form must reproduce the above copyright
*notice, this list of conditions and the following disclaimer in the
*documentation and/or other materials provided with the distribution.
*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
*IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
*TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
*PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
*HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
*OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the ocr-postcorrection tool developed
* by the IMPACT working group at the Centrum für Informations- und Sprachverarbeitung, University of Munich.
* For further information and contacts visit http://ocr.cis.uni-muenchen.de/
*
* @author thorsten (thorsten.vobl@googlemail.com)
*/
@ConvertAsProperties(dtd = "-//jav.gui.error//OCRFehler//EN",
autostore = false)
public final class OCRFehlerTopComponent extends AbstractMyTopComponent implements FontZoomCookie, TokenStatusEventSlot, DocumentChangedEventSlot {
private static OCRFehlerTopComponent instance;
private static final String PREFERRED_ID = "OCRFehlerTopComponent";
private Preferences node;
private InstanceContent content = new InstanceContent();
private int fontSize;
private OCRFehlerMode olm = new OCRFehlerDefaultMode();
private HashMap<String, OCRErrorInfo> errormap = null;
public OCRFehlerTopComponent() {
// initComponents();
this.setFocusable(true);
associateLookup(new AbstractLookup(content));
node = NbPreferences.forModule(this.getClass());
initialize();
jPanel1.setLayout(new BoxLayout(jPanel1,
BoxLayout.Y_AXIS));
jPanel1.setBackground(Color.white);
// show concordance button
jButton2.setEnabled(false);
jButton2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
olm.concordanceAction();
}
});
setName(NbBundle.getMessage(OCRFehlerTopComponent.class, "CTL_OCRFehlerTopComponent"));
setToolTipText(NbBundle.getMessage(OCRFehlerTopComponent.class, "HINT_OCRFehlerTopComponent"));
// setIcon(ImageUtilities.loadImage(ICON_PATH, true));
}
private void initialize() {
this.setLayout(new BorderLayout());
jToolBar1 = new javax.swing.JToolBar();
jButton2 = new javax.swing.JButton();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
jToolBar1.setRollover(true);
org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(OCRFehlerTopComponent.class, "OCRFehlerTopComponent.jButton2.text")); // NOI18N
jButton2.setFocusable(false);
jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
jToolBar1.add(jButton2);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane1.setWheelScrollingEnabled(true);
this.add(jToolBar1, BorderLayout.PAGE_START);
this.add(jScrollPane1, BorderLayout.CENTER);
}
private javax.swing.JButton jButton2;
private javax.swing.JToolBar jToolBar1;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files
* only, i.e. deserialization routines; otherwise you could get a
* non-deserialized instance. To obtain the singleton instance, use {@link #findInstance}.
*/
public static synchronized OCRFehlerTopComponent getDefault() {
if (instance == null) {
instance = new OCRFehlerTopComponent();
}
return instance;
}
/**
* Obtain the OCRFehlerTopComponent instance. Never call {@link #getDefault}
* directly!
*/
public static synchronized OCRFehlerTopComponent findInstance() {
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
if (win == null) {
Logger.getLogger(OCRFehlerTopComponent.class.getName()).warning(
"Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
return getDefault();
}
if (win instanceof OCRFehlerTopComponent) {
return (OCRFehlerTopComponent) win;
}
Logger.getLogger(OCRFehlerTopComponent.class.getName()).warning(
"There seem to be multiple components with the '" + PREFERRED_ID
+ "' ID. That is a potential source of errors and unexpected behavior.");
return getDefault();
}
@Override
public int getPersistenceType() {
return TopComponent.PERSISTENCE_ALWAYS;
}
void writeProperties(java.util.Properties p) {
// better to version settings since initial version as advocated at
// http://wiki.apidesign.org/wiki/PropertyFiles
p.setProperty("version", "1.0");
// TODO store your settings
}
Object readProperties(java.util.Properties p) {
if (instance == null) {
instance = this;
}
instance.readPropertiesImpl(p);
return instance;
}
private void readPropertiesImpl(java.util.Properties p) {
String version = p.getProperty("version");
// TODO read your settings according to their version
}
@Override
protected String preferredID() {
return PREFERRED_ID;
}
@Override
public void componentOpened() {
if (MainController.findInstance().getDocOpen()) {
displayErrorMap();
olm.setDocLoaded(true);
}
MessageCenter.getInstance().addDocumentChangedEventListener(this);
MessageCenter.getInstance().addTokenStatusEventListener(this);
}
@Override
public void componentClosed() {
MessageCenter.getInstance().removeDocumentChangedEventListener(this);
MessageCenter.getInstance().removeTokenStatusEventListener(this);
}
@Override
public void dispatchEvent(DocumentChangedEvent e) {
fontSize = Integer.parseInt(MainController.findInstance().getDocumentProperties().getProperty("ocrerrorFontSize"));
displayErrorMap();
olm.setDocLoaded(true);
}
public void displayErrorMap() {
SwingWorker<TreeMap<String, OCRErrorInfo>, Object> worker = new SwingWorker<TreeMap<String, OCRErrorInfo>, Object>() {
@Override
protected TreeMap<String, OCRErrorInfo> doInBackground() {
TreeMap<String, OCRErrorInfo> result = null;
try {
HashMap<String, OCRErrorInfo> errmap = MainController.findInstance().computeErrorFreqList();
errormap = errmap;
MyComparator comp = new MyComparator(errmap);
result = new TreeMap<>(comp);
result.putAll(errmap);
} catch (Exception e) {
// IOProvider.getDefault().getIO("", false).getOut().println(e.getMessage());
}
return result;
}
@Override
protected void done() {
try {
TreeMap<String, OCRErrorInfo> result = get();
if (result != null) {
content.remove(instance);
jPanel1.removeAll();
jPanel1.setLayout(new BoxLayout(jPanel1, BoxLayout.Y_AXIS));
Iterator<String> i = result.keySet().iterator();
while (i.hasNext()) {
String key = i.next();
OCRErrorInfo info = result.get(key);
if (info.getOccurencesN() > 1) {
OCRFehlerPanel panel = new OCRFehlerPanel(key, info, olm);
jPanel1.add(panel);
}
}
jScrollPane1.setViewportView(jPanel1);
content.add(instance);
} else {
}
} catch (ExecutionException ex) {
} catch (InterruptedException ex) {
} catch (CancellationException ex) {
}
}
};
jPanel1.setLayout(new BoxLayout(jPanel1, BoxLayout.Y_AXIS));
jPanel1.add(new JLabel("loading..."));
jScrollPane1.setViewportView(jPanel1);
worker.execute();
// this.revalidate();
}
@Override
public boolean isReady() {
if (jPanel1.getComponentCount() > 0) {
return true;
} else {
return false;
}
}
@Override
public void zoomFont(int i) {
content.remove(this);
for (Component c : jPanel1.getComponents()) {
if (c instanceof OCRFehlerPanel) {
OCRFehlerPanel pl = (OCRFehlerPanel) c;
pl.zoomFont(i);
}
}
this.fontSize = i;
MainController.findInstance().getDocumentProperties().setProperty("ocrerrorFontSize", "" + this.fontSize);
content.add(this);
jScrollPane1.revalidate();
this.revalidate();
}
@Override
public int getMaxFontSize() {
return node.getInt("maxFontSize", 40);
}
@Override
public int getMinFontSize() {
return node.getInt("minFontSize", 5);
}
@Override
public int getFontSize() {
return this.fontSize;
}
public void setKonkordanzButton(boolean b) {
jButton2.setEnabled(b);
}
@Override
public void dispatchEvent(final TokenStatusEvent e) {
if (e.getType().equals(TokenStatusType.CORRECTED)) {
CorrectedEvent ce = (CorrectedEvent) e;
if (errormap != null && errormap.containsKey(ce.getNewText())) {
OCRErrorInfo info = errormap.get(ce.getNewText());
if (ce.getSetTo()) {
info.addCorrected();
} else {
info.removeCorrected();
}
for (Component ca : jPanel1.getComponents()) {
JPanel p = (JPanel) ca;
OCRFehlerLabel l = (OCRFehlerLabel) p.getComponent(0);
if (ce.getNewText().equals(l.getText())) {
JLabel numl = (JLabel) p.getComponent(1);
int n = info.getOccurencesN() - info.getCorrected();
numl.setText("" + n);
break;
}
}
}
} else if(e.getType().equals(TokenStatusType.DELETE)) {
} else if(e.getType().equals(TokenStatusType.INSERT)) {
} else if(e.getType().equals(TokenStatusType.MERGED_RIGHT)) {
} else if(e.getType().equals(TokenStatusType.SPLIT)) {
}
// if (e.getType().equals(TokenStatusType.CORRECTED) || e.getType().equals(TokenStatusType.MERGED_RIGHT) || e.getType().equals(TokenStatusType.SPLIT)) {
// EventQueue.invokeLater(new Runnable() {
//
// @Override
// public void run() {
// String s = MainController.findInstance().getToken(e.getTokenIndex()).getWOCR();
// if (errormap != null && s != null) {
// if (errormap.containsKey(s)) {
// OCRErrorInfo info = errormap.get(s);
// info.addCorrected();
// if (info.getCorrected() == info.getOccurencesN()) {
// for (Component ca : jPanel1.getComponents()) {
// JPanel p = (JPanel) ca;
// OCRFehlerLabel l = (OCRFehlerLabel) p.getComponent(0);
// if (s.equals(l.getText())) {
// jPanel1.remove(ca);
// jPanel1.revalidate();
// break;
// }
// }
// } else {
// for (Component ca : jPanel1.getComponents()) {
// JPanel p = (JPanel) ca;
// OCRFehlerLabel l = (OCRFehlerLabel) p.getComponent(0);
// if (s.equals(l.getText())) {
// JLabel numl = (JLabel) p.getComponent(1);
// int n = info.getOccurencesN() - info.getCorrected();
// numl.setText("" + n);
// break;
// }
// }
// }
// }
// }
// }
// });
// }
}
}
class MyComparator implements Comparator<String> {
HashMap<String, OCRErrorInfo> theMapToSort;
public MyComparator(HashMap<String, OCRErrorInfo> theMapToSort) {
this.theMapToSort = theMapToSort;
}
@Override
public int compare(String s1, String s2) {
int val1 = theMapToSort.get(s1).getOccurencesN();
int val2 = theMapToSort.get(s2).getOccurencesN();
if (val1 < val2) {
return 1;
} else if (val1 > val2) {
return -1;
} else {
return s1.compareTo(s2);
}
}
}