/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2008 Alex Buloichik
2013 Aaron Madlon-Kay, 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;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.StyleConstants;
import org.omegat.core.data.ProtectedPart;
import org.omegat.util.Preferences;
import org.omegat.util.gui.UIThreadsUtil;
/**
* Own implementation of DocumentFilter. It required for disable for user's edit
* text outside translation.
*
* @author Alex Buloichik (alex73mail@gmail.com)
* @author Aaron Madlon-Kay
*/
public class DocumentFilter3 extends DocumentFilter {
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
UIThreadsUtil.mustBeSwingThread();
if (isPossible(fb.getDocument(), offset, length)) {
super.remove(fb, offset, length);
}
}
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
UIThreadsUtil.mustBeSwingThread();
if (attr != null) {
((Document3)fb.getDocument()).textBeingComposed = attr.isDefined(StyleConstants.ComposedTextAttribute);
}
if (isPossible(fb.getDocument(), offset, 0)) {
super.insertString(fb, offset, string, attr);
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
UIThreadsUtil.mustBeSwingThread();
if (attrs != null) {
((Document3)fb.getDocument()).textBeingComposed = attrs.isDefined(StyleConstants.ComposedTextAttribute);
}
if (isPossible(fb.getDocument(), offset, length)) {
super.replace(fb, offset, length, text, attrs);
}
}
private boolean isPossible(Document d, int offset, int length) throws BadLocationException {
Document3 doc = (Document3) d;
if (doc.trustedChangesInProgress) {
// this call created by internal changes
return true;
}
if (!doc.isEditMode()) {
// segment not active - change disabled
return false;
}
if (offset < doc.getTranslationStart() || offset + length > doc.getTranslationEnd()) {
// Is inside translation ?
return false;
}
// check protected parts
if (!Preferences.isPreference(Preferences.ALLOW_TAG_EDITING)) {
SegmentBuilder sb = doc.controller.getCurrentSegmentBuilder();
if (sb == null) {
// there is no current active entry
return false;
}
// check if inside tag
String text = doc.getText(doc.getTranslationStart(), doc.getTranslationEnd() - doc.getTranslationStart());
int off = offset - doc.getTranslationStart();
for (ProtectedPart pp : sb.ste.getProtectedParts()) {
int pos = -1;
while ((pos = text.indexOf(pp.getTextInSourceSegment(), pos + 1)) >= 0) {
int checkPos = pos;
int checkLen = pp.getTextInSourceSegment().length();
if (sb.hasRTL && doc.controller.targetLangIsRTL) {
// should be bidi-chars around tags
if (EditorUtils.hasBidiAroundTag(text, pp.getTextInSourceSegment(), pos)) {
checkPos -= 2;
checkLen += 4;
}
}
if (off > checkPos && off < checkPos + checkLen) {
return false;
}
if (off + length > checkPos && off + length < checkPos + checkLen) {
return false;
}
}
}
}
return true;
}
}