/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2013 Alex Buloichik
Home page: http://www.omegat.org/
Support center: http://groups.yahoo.com/group/OmegaT/
This file is part of OmegaT.
OmegaT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OmegaT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
package org.omegat.gui.editor.filter;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.omegat.core.Core;
import org.omegat.core.data.PrepareTMXEntry;
import org.omegat.core.data.SourceTextEntry;
import org.omegat.core.data.TMXEntry;
import org.omegat.core.search.SearchMatch;
import org.omegat.core.search.Searcher;
import org.omegat.gui.editor.EditorController;
import org.omegat.gui.editor.IEditor;
import org.omegat.gui.editor.IEditor.CaretPosition;
import org.omegat.gui.editor.IEditorFilter;
/**
* Editor filter implementation.
*
* @author Alex Buloichik (alex73mail@gmail.com)
*/
public class ReplaceFilter implements IEditorFilter {
private final Map<Integer, SourceTextEntry> entries = new HashMap<Integer, SourceTextEntry>();
private FilterBarReplace controlComponent;
private Searcher searcher;
private String replacement;
private int minEntryNum, maxEntryNum;
public ReplaceFilter(List<Integer> entriesList, Searcher searcher, String replacement) {
this.searcher = searcher;
this.replacement = replacement;
minEntryNum = Integer.MAX_VALUE;
maxEntryNum = Integer.MIN_VALUE;
Set<Integer> display = new HashSet<Integer>(entriesList);
for (SourceTextEntry ste : Core.getProject().getAllEntries()) {
minEntryNum = Math.min(minEntryNum, ste.entryNum());
maxEntryNum = Math.max(maxEntryNum, ste.entryNum());
if (display.contains(ste.entryNum())) {
entries.put(ste.entryNum(), ste);
}
}
controlComponent = new FilterBarReplace();
controlComponent.btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Core.getEditor().commitAndDeactivate(); // Make sure that any change done in the current segment is not lost
Core.getEditor().removeFilter();
}
});
controlComponent.btnSkip.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
skip();
}
});
controlComponent.btnReplaceNext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
replace();
}
});
}
@Override
public boolean isSourceAsEmptyTranslation() {
return true;
}
/**
* Replace all occurrences in all entries.
*/
public void replaceAll() {
for (SourceTextEntry ste : entries.values()) {
TMXEntry en = Core.getProject().getTranslationInfo(ste);
String trans = getEntryText(ste, en);
if (trans == null) {
continue;
}
List<SearchMatch> found = getReplacementsForEntry(trans);
if (found != null) {
int off = 0;
StringBuilder o = new StringBuilder(trans);
for (SearchMatch m : found) {
o.replace(m.getStart() + off, m.getEnd() + off, replacement);
off += replacement.length() - m.getLength();
}
PrepareTMXEntry prepare = new PrepareTMXEntry(en);
prepare.translation = o.toString();
Core.getProject().setTranslation(ste, prepare, en.defaultTranslation, null);
}
}
EditorController ec = (EditorController) Core.getEditor();
ec.refreshEntries(entries.keySet());
}
@Override
public boolean allowed(SourceTextEntry ste) {
return entries.containsKey(ste.entryNum());
}
@Override
public Component getControlComponent() {
return controlComponent;
}
public List<SearchMatch> getReplacementsForEntry(String translationText) {
if (searcher.searchString(translationText)) {
return searcher.getFoundMatches();
} else {
return null;
}
}
private void skip() {
EditorController ec = (EditorController) Core.getEditor();
// try to find in current entry
int pos = ec.getCurrentPositionInEntryTranslation();
String str = ec.getCurrentTranslation();
List<SearchMatch> found = getReplacementsForEntry(str);
if (found != null) {
for (SearchMatch m : found) {
if (m.getStart() > pos) {
ec.setCaretPosition(new IEditor.CaretPosition(m.getStart(), m.getEnd()));
ec.requestFocus();
return;
}
}
}
// not found in current entry - find next entry
int currentEntryNumber = ec.getCurrentEntryNumber();
ec.commitAndDeactivate();
// find to the end of project
for (int i = currentEntryNumber + 1; i <= maxEntryNum; i++) {
SourceTextEntry ste = entries.get(i);
if (ste == null) {
continue; // entry not filtered
}
TMXEntry en = Core.getProject().getTranslationInfo(ste);
String trans = getEntryText(ste, en);
if (trans == null) {
continue;
}
found = getReplacementsForEntry(trans);
if (found == null) {
continue; // no replacements
}
for (SearchMatch m : found) {
ec.gotoEntry(i, new CaretPosition(m.getStart(), m.getEnd()));
ec.requestFocus();
return;
}
}
// find from the beginning of project
for (int i = minEntryNum; i < currentEntryNumber; i++) {
SourceTextEntry ste = entries.get(i);
if (ste == null) {
continue; // entry not filtered
}
TMXEntry en = Core.getProject().getTranslationInfo(ste);
String trans = getEntryText(ste, en);
if (trans == null) {
continue;
}
found = getReplacementsForEntry(trans);
if (found == null) {
continue; // no replacements
}
for (SearchMatch m : found) {
ec.gotoEntry(i, new CaretPosition(m.getStart(), m.getEnd()));
ec.requestFocus();
return;
}
}
// not found
ec.activateEntry();
}
private void replace() {
EditorController ec = (EditorController) Core.getEditor();
// is caret inside match ?
int pos = ec.getCurrentPositionInEntryTranslation();
String str = ec.getCurrentTranslation();
List<SearchMatch> found = getReplacementsForEntry(str);
if (found != null) {
for (SearchMatch m : getReplacementsForEntry(str)) {
if (m.getStart() <= pos && pos <= m.getEnd()) {
// yes - replace
ec.replacePartOfText(replacement, m.getStart(), m.getEnd());
break;
}
}
}
// skip to next
skip();
}
/**
* Returns text of entry where replacement should be found. It can be translation or source text depends
* on settings, or null if entry should be skipped.
*/
private String getEntryText(SourceTextEntry ste, TMXEntry en) {
if (en.isTranslated()) {
return en.translation;
} else if (searcher.getExpression().replaceUntranslated) {
return ste.getSrcText();
} else {
return null;
}
}
}