/**************************************************************************
OmegaT - Computer Assisted Translation (CAT) tool
with fuzzy matching, translation memory, keyword search,
glossaries, and translation leveraging into updated projects.
Copyright (C) 2016 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.properties;
import java.awt.Component;
import java.awt.Font;
import java.awt.IllegalComponentStateException;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.reflect.Constructor;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.MissingResourceException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import org.apache.commons.lang.StringUtils;
import org.omegat.core.Core;
import org.omegat.core.CoreEvents;
import org.omegat.core.data.EntryKey;
import org.omegat.core.data.SourceTextEntry;
import org.omegat.core.data.SourceTextEntry.DUPLICATE;
import org.omegat.core.data.TMXEntry;
import org.omegat.core.events.IEntryEventListener;
import org.omegat.core.events.IFontChangedEventListener;
import org.omegat.core.events.IProjectEventListener;
import org.omegat.gui.main.DockableScrollPane;
import org.omegat.gui.main.IMainWindow;
import org.omegat.util.Log;
import org.omegat.util.OStrings;
import org.omegat.util.Preferences;
import org.omegat.util.StringUtil;
import org.omegat.util.gui.IPaneMenu;
import org.omegat.util.gui.Styles;
public class SegmentPropertiesArea implements IPaneMenu {
private final static Pattern SPLIT_COMMAS = Pattern.compile("\\s*,\\s*");
private final DateFormat dateFormat = DateFormat.getDateInstance();
private final DateFormat timeFormat = DateFormat.getTimeInstance();
private final static String KEY_ISDUP = "isDup";
private final static String KEY_FILE = "file";
private final static String KEY_ID = "id";
private final static String KEY_TRANSLATION = "translation";
private final static String KEY_TRANSLATIONISFUZZY = "translationIsFuzzy";
// private final static String KEY_NEXT = "next";
// private final static String KEY_PREV = "prev";
private final static String KEY_PATH = "path";
private final static String KEY_HASNOTE = "hasNote";
private final static String KEY_CHANGED = "changed";
private final static String KEY_CHANGER = "changer";
private final static String KEY_CREATED = "created";
private final static String KEY_CREATOR = "creator";
private final static String KEY_ISALT = "isAlt";
private final static String KEY_LINKED = "linked";
final List<String> properties = new ArrayList<String>();
final DockableScrollPane scrollPane;
private ISegmentPropertiesView viewImpl;
public SegmentPropertiesArea(IMainWindow mw) {
scrollPane = new DockableScrollPane("SEGMENTPROPERTIES", OStrings.getString("SEGPROP_PANE_TITLE"),
null, true);
mw.addDockable(scrollPane);
scrollPane.setMenuProvider(this);
CoreEvents.registerEntryEventListener(new IEntryEventListener() {
@Override
public void onNewFile(String activeFileName) {
}
@Override
public void onEntryActivated(SourceTextEntry newEntry) {
scrollPane.stopNotifying();
setProperties(newEntry);
doNotify(getKeysToNotify());
}
});
CoreEvents.registerProjectChangeListener(new IProjectEventListener() {
@Override
public void onProjectChanged(PROJECT_CHANGE_TYPE eventType) {
if (eventType == PROJECT_CHANGE_TYPE.CLOSE) {
setProperties(null);
}
}
});
CoreEvents.registerFontChangedEventListener(new IFontChangedEventListener() {
@Override
public void onFontChanged(Font newFont) {
viewImpl.getViewComponent().setFont(newFont);
}
});
scrollPane.setForeground(Styles.EditorColor.COLOR_FOREGROUND.getColor());
scrollPane.setBackground(Styles.EditorColor.COLOR_BACKGROUND.getColor());
scrollPane.getViewport().setBackground(Styles.EditorColor.COLOR_BACKGROUND.getColor());
Class<?> initModeClass = SegmentPropertiesTableView.class;
String initModeClassName = Preferences.getPreferenceDefault(Preferences.SEGPROPS_INITIAL_MODE, null);
if (initModeClassName != null) {
try {
initModeClass = getClass().getClassLoader().loadClass(initModeClassName);
} catch (ClassNotFoundException e1) {
Log.log(e1);
}
}
installView(initModeClass);
scrollPane.addMouseListener(contextMenuListener);
}
private void installView(Class<?> viewClass) {
if (viewImpl != null && viewImpl.getClass().equals(viewClass)) {
return;
}
ISegmentPropertiesView newImpl;
try {
Constructor<?> constructor = viewClass.getConstructor();
newImpl = (ISegmentPropertiesView) constructor.newInstance();
} catch (Throwable e) {
Logger.getLogger(getClass().getName()).log(Level.FINE, e.getMessage());
return;
}
viewImpl = newImpl;
viewImpl.install(this);
}
private void toggleMode(Class<?> newMode) {
installView(newMode);
Preferences.setPreference(Preferences.SEGPROPS_INITIAL_MODE, newMode.getName());
viewImpl.update();
}
final MouseListener contextMenuListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
doPopup(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
doPopup(e);
}
}
private void doPopup(MouseEvent e) {
Point p = SwingUtilities.convertPoint((Component) e.getSource(), e.getPoint(),
scrollPane);
showContextMenu(p);
}
};
void showContextMenu(Point p) {
JPopupMenu menu = new JPopupMenu();
populateLocalContextMenuOptions(menu, p);
// populateGlobalContextMenuOptions(menu);
try {
menu.show(scrollPane, p.x, p.y);
} catch (IllegalComponentStateException ignore) {
ignore.printStackTrace();
}
}
private void populateLocalContextMenuOptions(JPopupMenu contextMenu, Point p) {
final String key = viewImpl.getKeyAtPoint(p);
if (key == null) {
return;
}
String displayKey = key;
if (!Preferences.isPreference(Preferences.SEGPROPS_SHOW_RAW_KEYS)) {
try {
displayKey = OStrings
.getString(ISegmentPropertiesView.PROPERTY_TRANSLATION_KEY + key.toUpperCase());
} catch (MissingResourceException ignore) {
// If this is not a known key then we can't translate it,
// so use the "raw" key instead.
}
}
String label = StringUtil.format(OStrings.getString("SEGPROP_CONTEXTMENU_NOTIFY_ON_PROP"),
displayKey);
final JMenuItem notifyOnItem = new JCheckBoxMenuItem(label);
notifyOnItem.setSelected(getKeysToNotify().contains(key));
notifyOnItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setKeyToNotify(key, notifyOnItem.isSelected());
}
});
contextMenu.add(notifyOnItem);
}
@Override
public void populatePaneMenu(JPopupMenu contextMenu) {
JMenuItem tableModeItem = new JCheckBoxMenuItem(OStrings.getString("SEGPROP_CONTEXTMENU_TABLE_MODE"));
tableModeItem.setSelected(viewImpl.getClass().equals(SegmentPropertiesTableView.class));
tableModeItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
toggleMode(SegmentPropertiesTableView.class);
}
});
JMenuItem listModeItem = new JCheckBoxMenuItem(OStrings.getString("SEGPROP_CONTEXTMENU_LIST_MODE"));
listModeItem.setSelected(viewImpl.getClass().equals(SegmentPropertiesListView.class));
listModeItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
toggleMode(SegmentPropertiesListView.class);
}
});
ButtonGroup group = new ButtonGroup();
group.add(tableModeItem);
group.add(listModeItem);
contextMenu.add(tableModeItem);
contextMenu.add(listModeItem);
contextMenu.addSeparator();
final JMenuItem toggleKeyTranslationItem = new JCheckBoxMenuItem(
OStrings.getString("SEGPROP_CONTEXTMENU_RAW_KEYS"));
toggleKeyTranslationItem.setSelected(Preferences.isPreference(Preferences.SEGPROPS_SHOW_RAW_KEYS));
toggleKeyTranslationItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Preferences.setPreference(Preferences.SEGPROPS_SHOW_RAW_KEYS,
toggleKeyTranslationItem.isSelected());
viewImpl.update();
}
});
contextMenu.add(toggleKeyTranslationItem);
}
private List<String> getKeysToNotify() {
if (!Preferences.existsPreference(Preferences.SEGPROPS_NOTIFY_PROPS)) {
Preferences.setPreference(Preferences.SEGPROPS_NOTIFY_PROPS,
Preferences.SEGPROPS_NOTIFY_DEFAULT_PROPS);
}
String rawProps = Preferences.getPreference(Preferences.SEGPROPS_NOTIFY_PROPS);
return Arrays.asList(SPLIT_COMMAS.split(rawProps));
}
private void setKeyToNotify(String key, boolean enabled) {
List<String> currentKeys = new ArrayList<String>(getKeysToNotify());
if (enabled && !currentKeys.contains(key)) {
currentKeys.add(key);
}
if (!enabled && currentKeys.contains(key)) {
currentKeys.remove(key);
}
Preferences.setPreference(Preferences.SEGPROPS_NOTIFY_PROPS, StringUtils.join(currentKeys, ", "));
}
private void doNotify(List<String> keys) {
final List<Integer> notify = new ArrayList<Integer>();
for (int i = 0; i < properties.size(); i += 2) {
String prop = properties.get(i);
if (keys.contains(prop)) {
notify.add(i);
}
}
if (notify.isEmpty()) {
return;
}
Collections.sort(notify);
scrollPane.notify(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
viewImpl.notifyUser(notify);
}
});
}
private void setProperty(String key, String value) {
if (value != null) {
properties.add(key);
properties.add(value);
}
}
private void setProperty(String key, Object value) {
if (value != null) {
setProperty(key, value.toString());
}
}
private void setProperties(SourceTextEntry ste) {
properties.clear();
if (ste != null) {
for (String s : ste.getRawProperties()) {
properties.add(s);
}
if (ste.getDuplicate() != DUPLICATE.NONE) {
setProperty(KEY_ISDUP, ste.getDuplicate());
}
if (ste.getSourceTranslation() != null) {
setProperty(KEY_TRANSLATION, ste.getSourceTranslation());
if (ste.isSourceTranslationFuzzy()) {
setProperty(KEY_TRANSLATIONISFUZZY, true);
}
}
setKeyProperties(ste.getKey());
TMXEntry trg = Core.getProject().getTranslationInfo(ste);
setTranslationProperties(trg);
}
viewImpl.update();
}
private void setKeyProperties(EntryKey key) {
setProperty(KEY_FILE, key.file);
setProperty(KEY_ID, key.id);
// setProperty(KEY_NEXT, key.next);
// setProperty(KEY_PREV, key.prev);
setProperty(KEY_PATH, key.path);
}
private void setTranslationProperties(TMXEntry entry) {
if (entry.hasNote()) {
setProperty(KEY_HASNOTE, true);
}
if (!entry.isTranslated()) {
return;
}
if (entry.changeDate != 0) {
setProperty(KEY_CHANGED, dateFormat.format(new Date(entry.changeDate)) + " "
+ timeFormat.format(new Date(entry.changeDate)));
}
setProperty(KEY_CHANGER, entry.changer);
if (entry.creationDate != 0) {
setProperty(KEY_CREATED, dateFormat.format(new Date(entry.creationDate)) + " "
+ timeFormat.format(new Date(entry.creationDate)));
}
setProperty(KEY_CREATOR, entry.creator);
if (!entry.defaultTranslation) {
setProperty(KEY_ISALT, true);
}
setProperty(KEY_LINKED, entry.linked);
}
}