/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (martin_oat@yahoo.de)
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* SVN information:
* $Date: 2011-03-13 09:27:31 +0100 (Sun, 13 Mar 2011) $
* $Author: bananeweizen $
* $Revision: 6946 $
*/
package i18nplugin;
import java.awt.CardLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import tvbrowser.core.Settings;
import tvbrowser.core.icontheme.IconLoader;
import tvbrowser.core.plugin.PluginProxyManager;
import tvbrowser.core.tvdataservice.TvDataServiceProxyManager;
import util.exc.ErrorHandler;
import util.io.ZipUtil;
import util.ui.ExtensionFileFilter;
import util.ui.LinkButton;
import util.ui.Localizer;
import util.ui.SingleAndDoubleClickTreeUI;
import util.ui.TVBrowserIcons;
import util.ui.UiUtilities;
import util.ui.WindowClosingIf;
import com.jgoodies.forms.builder.ButtonBarBuilder2;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.DefaultComponentFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.Sizes;
import devplugin.Channel;
/**
* The Dialog for the Translation-Tool
*
* Attention: This Plugin uses some Core-Stuff, but "normal" Plugins are not allowed
* to do this !
*
* @author bodum
*/
final public class TranslationDialog extends JDialog implements WindowClosingIf {
/** Translator */
private static final Localizer mLocalizer = Localizer.getLocalizerFor(TranslationDialog.class);
private static final String EDITOR = "EDITOR";
private static final String HELP = "HELP";
private JTree mTree;
private PropertiesTreeCellRenderer mTreeRenderer;
private TranslatorEditor mEditor;
private UnsortedPathNode mRoot;
private Vector<Locale> mCurrentLocales;
private JComboBox mLanguageCB;
private JSplitPane mSplitpane;
private JTextField mFilterTF;
private JButton mClearFilterB;
public TranslationDialog(final Window owner, final int splitPos) {
super(owner);
setModal(true);
createGui(splitPos);
}
private void createGui(final int splitPos) {
setTitle(mLocalizer.msg("title","Translation Tool"));
JPanel panel = (JPanel) getContentPane();
panel.setBorder(Borders.DLU4_BORDER);
panel.setLayout(new FormLayout("3dlu, left:pref, 3dlu, pref, 3dlu, pref, fill:pref:grow, 3dlu", "pref, 5dlu, pref, 3dlu, pref, 5dlu, pref, 5dlu, fill:10dlu:grow, 3dlu, pref"));
CellConstraints cc = new CellConstraints();
panel.add(DefaultComponentFactory.getInstance().createSeparator(mLocalizer.msg("chooseLanguage", "Choose Language")), cc.xyw(1,1,8));
panel.add(new JLabel(mLocalizer.msg("language", "Language:")), cc.xy(2,3));
mCurrentLocales = new Vector<Locale>();
Locale[] locales = mLocalizer.getAllAvailableLocales();
for (Locale locale : locales) {
if (!locale.getLanguage().equals("en")) {
mCurrentLocales.add(locale);
}
}
mLanguageCB = new JComboBox(mCurrentLocales);
mLanguageCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Locale loc = (Locale) mLanguageCB.getSelectedItem();
mTreeRenderer.setCurrentLocale(loc);
mEditor.save();
mEditor.setCurrentLocale(loc);
filterChanged(mFilterTF.getText());
mTree.repaint();
}
});
mLanguageCB.setRenderer(new DefaultListCellRenderer() {
public java.awt.Component getListCellRendererComponent(javax.swing.JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
return super.getListCellRendererComponent(list, ((Locale)value).getDisplayName(), index, isSelected, cellHasFocus);
}
});
panel.add(mLanguageCB, cc.xy(4,3));
JButton newButton = new JButton(TVBrowserIcons.newIcon(TVBrowserIcons.SIZE_SMALL));
newButton.setToolTipText(mLocalizer.msg("newLanguage", "Add new language"));
newButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addLanguage();
}
});
panel.add(newButton, cc.xy(6,3));
panel.add(DefaultComponentFactory.getInstance().createSeparator(mLocalizer.msg("translate", "Translate")), cc.xyw(1,5,8));
panel.add(new JLabel(mLocalizer.msg("search", "Search:")), cc.xy(2,7));
mFilterTF = new JTextField();
panel.add(mFilterTF, cc.xy(4,7));
mClearFilterB = new JButton(IconLoader.getInstance().getIconFromTheme("action", "process-stop", 16));
mClearFilterB.setEnabled(false);
mClearFilterB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mFilterTF.setText(null);
}
});
panel.add(mClearFilterB, cc.xy(6,7));
DefaultMutableTreeNode root = createRootNode();
mTree = new JTree(root) {
public void updateUI() {
setUI(new SingleAndDoubleClickTreeUI(SingleAndDoubleClickTreeUI.AUTO_COLLAPSE_EXPAND, getSelectionPath()));
invalidate();
}
};
mTreeRenderer = new PropertiesTreeCellRenderer(Locale.GERMAN);
mTree.setCellRenderer(mTreeRenderer);
mSplitpane = new JSplitPane();
mSplitpane.setLeftComponent(new JScrollPane(mTree));
panel.add(mSplitpane, cc.xyw(2,9,6));
mEditor = new TranslatorEditor(Locale.GERMAN);
final JPanel cardPanel = new JPanel(new CardLayout());
cardPanel.add(mEditor, EDITOR);
JEditorPane help = new JEditorPane("text/html",mLocalizer.msg("helpText", "<h1>Help missing</h1>"));
help.setEditable(false);
cardPanel.add(new JScrollPane(help, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER), HELP);
mTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
CardLayout cl = (CardLayout)(cardPanel.getLayout());
if (mTree.getSelectionPath() != null) {
Object node = mTree.getSelectionPath().getLastPathComponent();
if (node instanceof PropertiesEntryNode) {
mEditor.save();
mEditor.setSelectedProperties((PropertiesEntryNode) node);
cl.show(cardPanel, EDITOR);
} else {
cl.show(cardPanel, HELP);
}
} else {
cl.show(cardPanel, HELP);
}
}
});
mTree.setSelectionPath(new TreePath(root));
mSplitpane.setRightComponent(cardPanel);
if (splitPos > 0) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
mSplitpane.setDividerLocation(splitPos);
}
});
}
ButtonBarBuilder2 buttonbar = new ButtonBarBuilder2();
JButton save = new JButton(mLocalizer.msg("save","Save"));
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
save();
}
});
JButton cancel = new JButton(Localizer.getLocalization(Localizer.I18N_CANCEL));
cancel.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
close();
}
});
JButton export = new JButton(IconLoader.getInstance().getIconFromTheme("actions", "document-save-as", 16));
export.setToolTipText(mLocalizer.msg("export", "Export Translations to File"));
export.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
export();
}
});
LinkButton link = new LinkButton(mLocalizer.msg("getHelp", "Get Help"), mLocalizer.msg("getHelpUrl", "http://enwiki.tvbrowser.org"));
buttonbar.addFixed(export);
buttonbar.addGlue();
buttonbar.addFixed(link);
buttonbar.addGlue();
buttonbar.addButton(new JButton[] {save, cancel});
panel.add(buttonbar.getPanel(), cc.xyw(2,11,6));
getRootPane().setDefaultButton(cancel);
UiUtilities.registerForClosing(this);
setSize(Sizes.dialogUnitXAsPixel(500, this), Sizes.dialogUnitYAsPixel(410, this));
mLanguageCB.setSelectedIndex(0);
mFilterTF.getDocument().addDocumentListener(new DocumentListener() {
public void removeUpdate(DocumentEvent e) {
filterChanged(mFilterTF.getText());
}
public void insertUpdate(DocumentEvent e) {
filterChanged(mFilterTF.getText());
}
public void changedUpdate(DocumentEvent e) {
filterChanged(mFilterTF.getText());
}
});
}
/**
* Shows a Dialog with a List of all available Languages
* and adds a selected Language
*/
void addLanguage() {
LanguageChooser dialog = new LanguageChooser(this, mCurrentLocales);
UiUtilities.centerAndShow(dialog);
Locale locale = dialog.getSelectedLocale();
if (locale != null) {
mCurrentLocales.add(locale);
Collections.sort(mCurrentLocales, new Comparator<Locale>() {
public int compare(Locale o1, Locale o2) {
return o1.getDisplayName().compareTo(o2.getDisplayName());
}
});
StringBuilder buffer = new StringBuilder(Settings
.getUserSettingsDirName());
buffer.append("/lang/tvbrowser/tvbrowser");
buffer.append('_').append(locale.getLanguage());
if (locale.getCountry().length() > 0) {
buffer.append('_').append(locale.getCountry());
}
if (locale.getVariant().length() > 0) {
buffer.append('_').append(locale.getVariant());
}
buffer.append(".properties");
try {
File file = new File(buffer.toString());
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
mLanguageCB.setModel(new DefaultComboBoxModel(mCurrentLocales));
mLanguageCB.setSelectedItem(dialog.getSelectedLocale());
}
}
/**
* Saves the current editor field and stores the changes of the user to his user directory
*/
void save() {
mEditor.save();
try {
mRoot.save();
} catch (Exception e) {
e.printStackTrace();
ErrorHandler.handle(mLocalizer.msg("problemWhileSaving","Problems while storing translations."), e);
}
close();
}
/**
* Opens a FileChooser and stores all User-Settings in a zip file
*/
private void export() {
JFileChooser fileChooser=new JFileChooser();
ExtensionFileFilter filter = new ExtensionFileFilter(".zip","Zip (*.zip)");
fileChooser.setFileFilter(filter);
int retVal = fileChooser.showSaveDialog(this);
if (retVal == JFileChooser.APPROVE_OPTION) {
File f=fileChooser.getSelectedFile();
if (f!=null) {
if (f.getName().indexOf('.') == -1) {
f = new File(f.getAbsolutePath() + filter.getExtension());
}
ZipUtil zip = new ZipUtil();
StringBuilder dir = new StringBuilder(Settings.getUserSettingsDirName())
.append(File.separatorChar).append("lang").append(
File.separatorChar);
try {
zip.zipDirectory(f, new File(dir.toString()));
JOptionPane.showMessageDialog(this, mLocalizer.msg("exportDone", "Export Done!"));
} catch (IOException e) {
e.printStackTrace();
ErrorHandler.handle(mLocalizer.msg("exportFailure", "Error while saving zip file."), e);
}
}
}
}
/**
* Creates the Root-Node for the Tree on the Left.
*
* The Tree has two Nodes:
*
* 1. TV-Browser
* 2. All Plugins
*
* @return new RootNOde
*/
private DefaultMutableTreeNode createRootNode() {
mRoot = new UnsortedPathNode(mLocalizer.msg("translations", "Translations"));
File jar = new File("tvbrowser.jar");
if (!jar.exists()) {
URL url = Channel.class.getProtectionDomain().getCodeSource().getLocation();
jar = new File(url.getFile());
}
if (!jar.exists()) {
JOptionPane.showConfirmDialog(null, "Jar not found : " + jar.getAbsolutePath());
}
mRoot.add(new TranslationNode("TV-Browser", jar));
PathNode plugins = new PathNode("Plugins");
addJarFiles(plugins, new File(Settings.propPluginsDirectory.getString()));
addJarFiles(plugins, new File(PluginProxyManager.PLUGIN_DIRECTORY));
addJarFiles(plugins, new File(TvDataServiceProxyManager.PLUGIN_DIRECTORY));
mRoot.add(plugins);
return mRoot;
}
/**
* Adds all Jar-Files in a Directory to a Tree
*
* @param treenode Add to this TreeNode
* @param dir add all Jars in this directory
*/
private void addJarFiles(DefaultMutableTreeNode treenode, File dir) {
File[] files = dir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".jar");
}
});
if (files != null) {
for (File file : files) {
TranslationNode node = new TranslationNode(file.getName(), file);
if (node.getChildCount() > 0) {
treenode.add(node);
}
}
}
}
public void close() {
setVisible(false);
}
/**
* @return Location of the Divider
*/
public int getDividerLocation() {
return mSplitpane.getDividerLocation();
}
/**
* Triggers the filtering of the tree.
*
* @param filterText
*/
private void filterChanged(final String filterText) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String filter = filterText;
if (filter.trim().length() == 0) {
filter = null;
}
mClearFilterB.setEnabled(filter != null);
if (mRoot != null && mLanguageCB != null) {
DefaultTreeModel model = (DefaultTreeModel) mTree.getModel();
TreePath[] selectionPaths = mTree.getSelectionPaths();
Enumeration<TreePath> expandedDescendants = mTree.getExpandedDescendants(new TreePath(model.getRoot()));
mRoot.setFilter((Locale) mLanguageCB.getSelectedItem(), filter);
model.reload();
while (expandedDescendants.hasMoreElements()) {
mTree.expandPath(expandedDescendants.nextElement());
} // while
mTree.setSelectionPaths(selectionPaths);
}
}
});
}
}