/**************************************************************************
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
2012 Martin Fleurke, Hans-Peter Jacobs
2015 Aaron Madlon-Kay
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 java.awt.Color;
import java.awt.event.KeyEvent;
import javax.swing.text.AttributeSet;
import org.omegat.core.Core;
import org.omegat.core.data.SourceTextEntry.DUPLICATE;
import org.omegat.core.spellchecker.SpellCheckerMarker;
import org.omegat.util.Preferences;
import org.omegat.util.gui.Styles;
import org.omegat.util.gui.UIThreadsUtil;
/**
* Editor behavior control settings.
*
* @author Alex Buloichik (alex73mail@gmail.com)
* @author Martin Fleurke
* @author Hans-Peter Jacobs
* @author Aaron Madlon-Kay
*/
public class EditorSettings implements IEditorSettings {
private final EditorController parent;
private boolean useTabForAdvance;
private boolean markTranslated;
private boolean markUntranslated;
private boolean markAutoPopulated;
private boolean displaySegmentSources;
private boolean markNonUniqueSegments;
private boolean markNoted;
private boolean markNBSP;
private boolean markWhitespace;
private boolean markBidi;
private String displayModificationInfo;
private boolean autoSpellChecking;
private boolean viewSourceBold;
private boolean markFirstNonUnique;
private boolean markLanguageChecker;
private boolean doFontFallback;
public static final String DISPLAY_MODIFICATION_INFO_NONE = "none";
public static final String DISPLAY_MODIFICATION_INFO_SELECTED = "selected";
public static final String DISPLAY_MODIFICATION_INFO_ALL = "all";
protected EditorSettings(final EditorController parent) {
this.parent = parent;
//options from menu 'view'
useTabForAdvance = Preferences.isPreference(Preferences.USE_TAB_TO_ADVANCE);
markTranslated = Preferences.isPreference(Preferences.MARK_TRANSLATED_SEGMENTS);
markUntranslated = Preferences.isPreference(Preferences.MARK_UNTRANSLATED_SEGMENTS);
displaySegmentSources = Preferences.isPreference(Preferences.DISPLAY_SEGMENT_SOURCES);
markNonUniqueSegments = Preferences.isPreference(Preferences.MARK_NON_UNIQUE_SEGMENTS);
markNoted = Preferences.isPreference(Preferences.MARK_NOTED_SEGMENTS);
markNBSP = Preferences.isPreference(Preferences.MARK_NBSP);
markWhitespace = Preferences.isPreference(Preferences.MARK_WHITESPACE);
markBidi = Preferences.isPreference(Preferences.MARK_BIDI);
displayModificationInfo = Preferences.getPreferenceDefault(Preferences.DISPLAY_MODIFICATION_INFO,
DISPLAY_MODIFICATION_INFO_NONE);
autoSpellChecking = Preferences.isPreference(Preferences.ALLOW_AUTO_SPELLCHECKING);
markAutoPopulated = Preferences.isPreference(Preferences.MARK_AUTOPOPULATED);
//options from menu options->view
viewSourceBold = Preferences.isPreferenceDefault(Preferences.VIEW_OPTION_SOURCE_ALL_BOLD,
Preferences.VIEW_OPTION_SOURCE_ALL_BOLD_DEFAULT);
markFirstNonUnique = Preferences.isPreference(Preferences.VIEW_OPTION_UNIQUE_FIRST);
markLanguageChecker = !Preferences.isPreferenceDefault(Preferences.LT_DISABLED,
Preferences.LT_DISABLED_DEFAULT);
doFontFallback = Preferences.isPreference(Preferences.FONT_FALLBACK);
}
public char getAdvancerChar() {
if (useTabForAdvance) {
return KeyEvent.VK_TAB;
} else {
return KeyEvent.VK_ENTER;
}
}
public boolean isUseTabForAdvance() {
return useTabForAdvance;
}
public void setUseTabForAdvance(boolean useTabForAdvance) {
this.useTabForAdvance = useTabForAdvance;
Preferences.setPreference(Preferences.USE_TAB_TO_ADVANCE, useTabForAdvance);
}
public boolean isMarkTranslated() {
return markTranslated;
}
public void setMarkTranslated(boolean markTranslated) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markTranslated = markTranslated;
Preferences.setPreference(Preferences.MARK_TRANSLATED_SEGMENTS, markTranslated);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public boolean isMarkUntranslated() {
return markUntranslated;
}
public boolean isMarkAutoPopulated() {
return markAutoPopulated;
}
public void setMarkAutoPopulated(boolean val) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markAutoPopulated = val;
Preferences.setPreference(Preferences.MARK_AUTOPOPULATED, markAutoPopulated);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkUntranslated(boolean markUntranslated) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markUntranslated = markUntranslated;
Preferences.setPreference(Preferences.MARK_UNTRANSLATED_SEGMENTS, markUntranslated);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
/** display the segment sources or not */
public boolean isDisplaySegmentSources() {
return displaySegmentSources;
}
public boolean isMarkNonUniqueSegments() {
return markNonUniqueSegments;
}
public boolean isHideDuplicateSegments() {
return true;
}
public boolean isMarkNotedSegments() {
return markNoted;
}
/**
* mark non-breakable spaces?
*
* @return true when set, false otherwise
*/
public boolean isMarkNBSP() {
return markNBSP;
}
/**
* mark whitespace?
* @return true when set, false otherwise
*/
public boolean isMarkWhitespace() {
return markWhitespace;
}
/**
* mark Bidirectional control characters
* @return true when set, false otherwise
*/
public boolean isMarkBidi() {
return markBidi;
}
public boolean isDoFontFallback() {
return doFontFallback;
}
public void setDisplaySegmentSources(boolean displaySegmentSources) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.displaySegmentSources = displaySegmentSources;
Preferences.setPreference(Preferences.DISPLAY_SEGMENT_SOURCES, displaySegmentSources);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkNonUniqueSegments(boolean markNonUniqueSegments) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markNonUniqueSegments = markNonUniqueSegments;
Preferences.setPreference(Preferences.MARK_NON_UNIQUE_SEGMENTS, markNonUniqueSegments);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkNotedSegments(boolean markNotedSegments) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markNoted = markNotedSegments;
Preferences.setPreference(Preferences.MARK_NOTED_SEGMENTS, markNoted);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkNBSP(boolean markNBSP) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markNBSP = markNBSP;
Preferences.setPreference(Preferences.MARK_NBSP, markNBSP);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkWhitespace(boolean markWhitespace) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markWhitespace = markWhitespace;
Preferences.setPreference(Preferences.MARK_WHITESPACE, markWhitespace);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setMarkBidi(boolean markBidi) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markBidi = markBidi;
Preferences.setPreference(Preferences.MARK_BIDI, markBidi);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
public void setDoFontFallback(boolean doFontFalback) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.doFontFallback = doFontFalback;
Preferences.setPreference(Preferences.FONT_FALLBACK, doFontFalback);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
@Override
public boolean isMarkLanguageChecker() {
return markLanguageChecker;
}
@Override
public void setMarkLanguageChecker(boolean markLanguageChecker) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.markLanguageChecker = markLanguageChecker;
Preferences.setPreference(Preferences.LT_DISABLED, !markLanguageChecker);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
/**
* returns the setting for display the modification information or not
* Either DISPLAY_MODIFICATION_INFO_NONE,
* DISPLAY_MODIFICATION_INFO_SELECTED, DISPLAY_MODIFICATION_INFO_ALL
*/
public String getDisplayModificationInfo() {
return displayModificationInfo;
}
/**
* Sets the setting for display the modification information or not
*
* @param displayModificationInfo
* Either DISPLAY_MODIFICATION_INFO_NONE ,
* DISPLAY_MODIFICATION_INFO_SELECTED ,
* DISPLAY_MODIFICATION_INFO_ALL
*/
public void setDisplayModificationInfo(String displayModificationInfo) {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
this.displayModificationInfo = displayModificationInfo;
Preferences.setPreference(Preferences.DISPLAY_MODIFICATION_INFO, displayModificationInfo);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
/** need to check spell or not */
public boolean isAutoSpellChecking() {
return autoSpellChecking;
}
public void setAutoSpellChecking(boolean autoSpellChecking) {
UIThreadsUtil.mustBeSwingThread();
if (Core.getProject().isProjectLoaded()) {
parent.commitAndDeactivate();
}
this.autoSpellChecking = autoSpellChecking;
if (Core.getProject().isProjectLoaded()) {
// parent.loadDocument();
parent.activateEntry();
parent.remarkOneMarker(SpellCheckerMarker.class.getName());
}
}
/**
* repaint segments in editor according to new view options. Use when options change to make them effective
* immediately.
*/
public void updateViewPreferences() {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
//update variables
viewSourceBold = Preferences.isPreference(Preferences.VIEW_OPTION_SOURCE_ALL_BOLD);
markFirstNonUnique = Preferences.isPreference(Preferences.VIEW_OPTION_UNIQUE_FIRST);
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
/**
* repaint segments in editor according to new view tag validation options. Use when options change to make them
* effective immediately.
*/
public void updateTagValidationPreferences() {
UIThreadsUtil.mustBeSwingThread();
parent.commitAndDeactivate();
// nothing special to do: tags/placeholders are determined by segment builder and info is passed as argument to
// getattributeSet.
if (Core.getProject().isProjectLoaded()) {
parent.loadDocument();
parent.activateEntry();
}
}
/**
* Choose segment's attributes based on rules.
*
* @param isSource
* is it a source segment or a target segment
* @param isPlaceholder
* is it for a placeholder (OmegaT tag or sprintf-variable etc.) or regular text inside the segment?
* @param isremovetext
* is it text that should be removed from translation?
* @param duplicate
* is the sourceTextEntry a duplicate or not? values: DUPLICATE.NONE, DUPLICATE.FIRST or DUPLICATE.NEXT.
* See sourceTextEntryste.getDuplicate()
* @param active
* is it an active segment?
* @param translationExists
* does a translation already exist
* @param isNBSP
* is the text a non-breakable space
* @return proper AttributeSet to use on displaying the segment.
*/
public AttributeSet getAttributeSet(boolean isSource, boolean isPlaceholder, boolean isRemoveText,
DUPLICATE duplicate, boolean active, boolean translationExists, boolean hasNote, boolean isNBSP) {
// determine foreground color
Color fg = null;
// Custom foreground colors
if (active) {
if (isSource) {
fg = Styles.EditorColor.COLOR_ACTIVE_SOURCE_FG.getColor();
} else {
fg = Styles.EditorColor.COLOR_ACTIVE_TARGET_FG.getColor();
}
} else {
if (isSource) {
if (isMarkNotedSegments() && hasNote && !translationExists) {
fg = Styles.EditorColor.COLOR_NOTED_FG.getColor();
} else if (markUntranslated && !translationExists) {
fg = Styles.EditorColor.COLOR_UNTRANSLATED_FG.getColor();
} else if (isDisplaySegmentSources()) {
fg = Styles.EditorColor.COLOR_SOURCE_FG.getColor();
}
} else {
if (isMarkNotedSegments() && hasNote) {
fg = Styles.EditorColor.COLOR_NOTED_FG.getColor();
} else if (markTranslated) {
fg = Styles.EditorColor.COLOR_TRANSLATED_FG.getColor();
}
}
}
if (markNonUniqueSegments) {
switch (duplicate) {
case NONE:
break;
case FIRST:
if (markFirstNonUnique) {
fg = Styles.EditorColor.COLOR_NON_UNIQUE.getColor();
}
break;
case NEXT:
fg = Styles.EditorColor.COLOR_NON_UNIQUE.getColor();
break;
}
}
if (isPlaceholder) {
fg = Styles.EditorColor.COLOR_PLACEHOLDER.getColor();
}
if (isRemoveText && !isSource) {
fg = Styles.EditorColor.COLOR_REMOVETEXT_TARGET.getColor();
}
//determine background color
Color bg = null;
if (active) {
if (isSource) {
bg = Styles.EditorColor.COLOR_ACTIVE_SOURCE.getColor();
} else {
bg = Styles.EditorColor.COLOR_ACTIVE_TARGET.getColor();
}
} else {
if (isSource) {
if (isMarkNotedSegments() && hasNote && !translationExists) {
bg = Styles.EditorColor.COLOR_NOTED.getColor();
} else if (markUntranslated && !translationExists) {
bg = Styles.EditorColor.COLOR_UNTRANSLATED.getColor();
} else if (isDisplaySegmentSources()) {
bg = Styles.EditorColor.COLOR_SOURCE.getColor();
}
} else {
if (isMarkNotedSegments() && hasNote) {
bg = Styles.EditorColor.COLOR_NOTED.getColor();
} else if (markTranslated) {
bg = Styles.EditorColor.COLOR_TRANSLATED.getColor();
}
}
}
Color nonUniqueBg = Styles.EditorColor.COLOR_NON_UNIQUE_BG.getColor();
if (markNonUniqueSegments && nonUniqueBg != null) {
switch (duplicate) {
case NONE:
break;
case FIRST:
if (markFirstNonUnique) {
bg = nonUniqueBg;
}
break;
case NEXT:
bg = nonUniqueBg;
break;
}
}
if (isNBSP && isMarkNBSP()) { //overwrite others, because space is smallest.
bg = Styles.EditorColor.COLOR_NBSP.getColor();
}
//determine bold
Boolean bold = false;
if (isSource) {
if (active || viewSourceBold && isDisplaySegmentSources()) {
bold = true;
}
}
//determine italic
Boolean italic = false;
if (isRemoveText && isSource) {
italic = true;
}
return Styles.createAttributeSet(fg, bg, bold, italic);
}
/**
* Returns font attributes for the modification info line.
* @return
*/
public AttributeSet getModificationInfoAttributeSet() {
return Styles.createAttributeSet(Styles.EditorColor.COLOR_MOD_INFO_FG.getColor(),
Styles.EditorColor.COLOR_MOD_INFO.getColor(), false, true);
}
/**
* Returns font attributes for the segment marker.
*
* @return
*/
public AttributeSet getSegmentMarkerAttributeSet() {
return Styles.createAttributeSet(Styles.EditorColor.COLOR_SEGMENT_MARKER_FG.getColor(),
Styles.EditorColor.COLOR_SEGMENT_MARKER_BG.getColor(), true, false);
}
/**
* Returns font attributes for other laguages translation.
*
* @return
*/
public AttributeSet getOtherLanguageTranslationAttributeSet() {
return Styles.createAttributeSet(Styles.EditorColor.COLOR_SOURCE_FG.getColor(),
Styles.EditorColor.COLOR_SOURCE.getColor(), false, true);
}
}