aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java653
1 files changed, 653 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java
new file mode 100644
index 000000000..0301b80fe
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newxmlfile/AddTranslationDialog.java
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.internal.wizards.newxmlfile;
+
+import static com.android.SdkConstants.FD_RES;
+import static com.android.SdkConstants.FD_RES_VALUES;
+import static com.android.SdkConstants.RES_QUALIFIER_SEP;
+
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.res2.ValueXmlHelper;
+import com.android.ide.common.resources.LocaleManager;
+import com.android.ide.common.resources.ResourceItem;
+import com.android.ide.common.resources.configuration.FolderConfiguration;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtUtils;
+import com.android.ide.eclipse.adt.internal.editors.layout.configuration.FlagManager;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderPreviewManager;
+import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.resources.ResourceType;
+import com.google.common.base.Charsets;
+import com.google.common.collect.Maps;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CellLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+
+/**
+ * Dialog which adds a new translation to the project
+ */
+public class AddTranslationDialog extends Dialog implements ControlListener, SelectionListener,
+ TraverseListener {
+ private static final int KEY_COLUMN = 0;
+ private static final int DEFAULT_TRANSLATION_COLUMN = 1;
+ private static final int NEW_TRANSLATION_COLUMN = 2;
+ private final FolderConfiguration mConfiguration = new FolderConfiguration();
+ private final IProject mProject;
+ private String mTarget;
+ private boolean mIgnore;
+ private Map<String, String> mTranslations;
+ private Set<String> mExistingLanguages;
+ private String mSelectedLanguage;
+ private String mSelectedRegion;
+
+ private Table mTable;
+ private Combo mLanguageCombo;
+ private Combo mRegionCombo;
+ private ImageControl mFlag;
+ private Label mFile;
+ private Button mOkButton;
+ private Composite mErrorPanel;
+ private Label mErrorLabel;
+ private MyTableViewer mTableViewer;
+
+ /**
+ * Creates the dialog.
+ * @param parentShell the parent shell
+ * @param project the project to add translations into
+ */
+ public AddTranslationDialog(Shell parentShell, IProject project) {
+ super(parentShell);
+ setShellStyle(SWT.CLOSE | SWT.RESIZE | SWT.TITLE);
+ mProject = project;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ GridLayout gl_container = new GridLayout(6, false);
+ gl_container.horizontalSpacing = 0;
+ container.setLayout(gl_container);
+
+ Label languageLabel = new Label(container, SWT.NONE);
+ languageLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ languageLabel.setText("Language:");
+ mLanguageCombo = new Combo(container, SWT.READ_ONLY);
+ GridData gd_mLanguageCombo = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
+ gd_mLanguageCombo.widthHint = 150;
+ mLanguageCombo.setLayoutData(gd_mLanguageCombo);
+
+ Label regionLabel = new Label(container, SWT.NONE);
+ GridData gd_regionLabel = new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1);
+ gd_regionLabel.horizontalIndent = 10;
+ regionLabel.setLayoutData(gd_regionLabel);
+ regionLabel.setText("Region:");
+ mRegionCombo = new Combo(container, SWT.READ_ONLY);
+ GridData gd_mRegionCombo = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
+ gd_mRegionCombo.widthHint = 150;
+ mRegionCombo.setLayoutData(gd_mRegionCombo);
+ mRegionCombo.setEnabled(false);
+
+ mFlag = new ImageControl(container, SWT.NONE, null);
+ mFlag.setDisposeImage(false);
+ GridData gd_mFlag = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
+ gd_mFlag.exclude = true;
+ gd_mFlag.widthHint = 32;
+ gd_mFlag.horizontalIndent = 3;
+ mFlag.setLayoutData(gd_mFlag);
+
+ mFile = new Label(container, SWT.NONE);
+ mFile.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ mTableViewer = new MyTableViewer(container, SWT.BORDER | SWT.FULL_SELECTION);
+ mTable = mTableViewer.getTable();
+ mTable.setEnabled(false);
+ mTable.setLinesVisible(true);
+ mTable.setHeaderVisible(true);
+ mTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 6, 2));
+ mTable.addControlListener(this);
+ mTable.addTraverseListener(this);
+ // If you have difficulty opening up this form in WindowBuilder and it complains about
+ // the next line, change the type of the mTableViewer field and the above
+ // constructor call from MyTableViewer to TableViewer
+ TableViewerColumn keyViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
+ TableColumn keyColumn = keyViewerColumn.getColumn();
+ keyColumn.setWidth(100);
+ keyColumn.setText("Key");
+ TableViewerColumn defaultViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
+ TableColumn defaultColumn = defaultViewerColumn.getColumn();
+ defaultColumn.setWidth(200);
+ defaultColumn.setText("Default");
+ TableViewerColumn translationViewerColumn = new TableViewerColumn(mTableViewer, SWT.NONE);
+ TableColumn translationColumn = translationViewerColumn.getColumn();
+ translationColumn.setWidth(200);
+ translationColumn.setText("New Translation");
+
+ mErrorPanel = new Composite(container, SWT.NONE);
+ GridData gd_mErrorLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 6, 1);
+ gd_mErrorLabel.exclude = true;
+ mErrorPanel.setLayoutData(gd_mErrorLabel);
+
+ translationViewerColumn.setEditingSupport(new TranslationEditingSupport(mTableViewer));
+
+ fillLanguages();
+ fillRegions();
+ fillStrings();
+ updateColumnWidths();
+ validatePage();
+
+ mLanguageCombo.addSelectionListener(this);
+ mRegionCombo.addSelectionListener(this);
+
+ return container;
+ }
+
+ /** Populates the table with keys and default strings */
+ private void fillStrings() {
+ ResourceManager manager = ResourceManager.getInstance();
+ ProjectResources resources = manager.getProjectResources(mProject);
+ mExistingLanguages = resources.getLanguages();
+
+ Collection<ResourceItem> items = resources.getResourceItemsOfType(ResourceType.STRING);
+
+ ResourceItem[] array = items.toArray(new ResourceItem[items.size()]);
+ Arrays.sort(array);
+
+ // TODO: Read in the actual XML files providing the default keys here
+ // (they can be obtained via ResourceItem.getSourceFileList())
+ // such that we can read all the attributes associated with each
+ // item, and if it defines translatable=false, or the filename is
+ // donottranslate.xml, we can ignore it, and in other cases just
+ // duplicate all the attributes (such as "formatted=true", or other
+ // local conventions such as "product=tablet", or "msgid="123123123",
+ // etc.)
+
+ mTranslations = Maps.newHashMapWithExpectedSize(items.size());
+ IBaseLabelProvider labelProvider = new CellLabelProvider() {
+ @Override
+ public void update(ViewerCell cell) {
+ Object element = cell.getElement();
+ int index = cell.getColumnIndex();
+ ResourceItem item = (ResourceItem) element;
+ switch (index) {
+ case KEY_COLUMN: {
+ // Key
+ cell.setText(item.getName());
+ return;
+ }
+ case DEFAULT_TRANSLATION_COLUMN: {
+ // Default translation
+ ResourceValue value = item.getResourceValue(ResourceType.STRING,
+ mConfiguration, false);
+
+ if (value != null) {
+ cell.setText(value.getValue());
+ return;
+ }
+ break;
+ }
+ case NEW_TRANSLATION_COLUMN: {
+ // New translation
+ String translation = mTranslations.get(item.getName());
+ if (translation != null) {
+ cell.setText(translation);
+ return;
+ }
+ break;
+ }
+ default:
+ assert false : index;
+ }
+ cell.setText("");
+ }
+ };
+
+ mTableViewer.setLabelProvider(labelProvider);
+ mTableViewer.setContentProvider(new ArrayContentProvider());
+ mTableViewer.setInput(array);
+ }
+
+ /** Populate the languages dropdown */
+ private void fillLanguages() {
+ List<String> languageCodes = LocaleManager.getLanguageCodes();
+ List<String> labels = new ArrayList<String>();
+ for (String code : languageCodes) {
+ labels.add(code + ": " + LocaleManager.getLanguageName(code)); //$NON-NLS-1$
+ }
+ Collections.sort(labels);
+ labels.add(0, "(Select)");
+ mLanguageCombo.setItems(labels.toArray(new String[labels.size()]));
+ mLanguageCombo.select(0);
+ }
+
+ /** Populate the regions dropdown */
+ private void fillRegions() {
+ // TODO: When you switch languages, offer some "default" usable options. For example,
+ // when you choose English, offer the countries that use English, and so on. Unfortunately
+ // we don't have good data about this, we'd just need to hardcode a few common cases.
+ List<String> regionCodes = LocaleManager.getRegionCodes();
+ List<String> labels = new ArrayList<String>();
+ for (String code : regionCodes) {
+ labels.add(code + ": " + LocaleManager.getRegionName(code)); //$NON-NLS-1$
+ }
+ Collections.sort(labels);
+ labels.add(0, "Any");
+ mRegionCombo.setItems(labels.toArray(new String[labels.size()]));
+ mRegionCombo.select(0);
+ }
+
+ /** React to resizing by distributing the space evenly between the last two columns */
+ private void updateColumnWidths() {
+ Rectangle r = mTable.getClientArea();
+ int availableWidth = r.width;
+ // Distribute all available space to the last two columns
+ int columnCount = mTable.getColumnCount();
+ for (int i = 0; i < columnCount; i++) {
+ TableColumn column = mTable.getColumn(i);
+ availableWidth -= column.getWidth();
+ }
+ if (availableWidth != 0) {
+ TableColumn column = mTable.getColumn(DEFAULT_TRANSLATION_COLUMN);
+ column.setWidth(column.getWidth() + availableWidth / 2);
+ column = mTable.getColumn(NEW_TRANSLATION_COLUMN);
+ column.setWidth(column.getWidth() + availableWidth / 2 + availableWidth % 2);
+ }
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ mOkButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+ // Don't make the OK button default as in most dialogs, since when you press
+ // Return thinking you might edit a value it dismisses the dialog instead
+ false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ mOkButton.setEnabled(false);
+
+ validatePage();
+ }
+
+ /**
+ * Return the initial size of the dialog.
+ */
+ @Override
+ protected Point getInitialSize() {
+ return new Point(800, 600);
+ }
+
+ private void updateTarget() {
+ if (mSelectedLanguage == null) {
+ mTarget = null;
+ mFile.setText("");
+ } else {
+ String folder = FD_RES + '/' + FD_RES_VALUES + RES_QUALIFIER_SEP + mSelectedLanguage;
+ if (mSelectedRegion != null) {
+ folder = folder + RES_QUALIFIER_SEP + 'r' + mSelectedRegion;
+ }
+ mTarget = folder + "/strings.xml"; //$NON-NLS-1$
+ mFile.setText(String.format("Creating %1$s", mTarget));
+ }
+ }
+
+ private void updateFlag() {
+ if (mSelectedLanguage == null) {
+ // Nothing selected
+ ((GridData) mFlag.getLayoutData()).exclude = true;
+ } else {
+ FlagManager manager = FlagManager.get();
+ Image flag = manager.getFlag(mSelectedLanguage, mSelectedRegion);
+ if (flag != null) {
+ ((GridData) mFlag.getLayoutData()).exclude = false;
+ mFlag.setImage(flag);
+ }
+ }
+
+ mFlag.getParent().layout(true);
+ mFlag.getParent().redraw();
+ }
+
+ /** Actually create the new translation file and write it to disk */
+ private void createTranslation() {
+ List<String> keys = new ArrayList<String>(mTranslations.keySet());
+ Collections.sort(keys);
+
+ StringBuilder sb = new StringBuilder(keys.size() * 120);
+ sb.append("<resources>\n\n"); //$NON-NLS-1$
+ for (String key : keys) {
+ String value = mTranslations.get(key);
+ if (value == null || value.trim().isEmpty()) {
+ continue;
+ }
+ sb.append(" <string name=\""); //$NON-NLS-1$
+ sb.append(key);
+ sb.append("\">"); //$NON-NLS-1$
+ sb.append(ValueXmlHelper.escapeResourceString(value));
+ sb.append("</string>\n"); //$NON-NLS-1$
+ }
+ sb.append("\n</resources>"); //$NON-NLS-1$
+
+ IFile file = mProject.getFile(mTarget);
+
+ try {
+ IContainer parent = file.getParent();
+ AdtUtils.ensureExists(parent);
+ InputStream source = new ByteArrayInputStream(sb.toString().getBytes(Charsets.UTF_8));
+ file.create(source, true, new NullProgressMonitor());
+ AdtPlugin.openFile(file, null, true /*showEditorTab*/);
+
+ // Ensure that the project resources updates itself to notice the new language.
+ // In theory, this shouldn't be necessary.
+ ResourceManager manager = ResourceManager.getInstance();
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IFolder folder = root.getFolder(parent.getFullPath());
+ manager.getResourceFolder(folder);
+ RenderPreviewManager.bumpRevision();
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+ }
+
+ private void validatePage() {
+ if (mOkButton == null) { // Early initialization
+ return;
+ }
+
+ String message = null;
+
+ if (mSelectedLanguage == null) {
+ message = "Select a language";
+ } else if (mExistingLanguages.contains(mSelectedLanguage)) {
+ if (mSelectedRegion == null) {
+ message = String.format("%1$s is already translated in this project",
+ LocaleManager.getLanguageName(mSelectedLanguage));
+ } else {
+ ResourceManager manager = ResourceManager.getInstance();
+ ProjectResources resources = manager.getProjectResources(mProject);
+ SortedSet<String> regions = resources.getRegions(mSelectedLanguage);
+ if (regions.contains(mSelectedRegion)) {
+ message = String.format("%1$s (%2$s) is already translated in this project",
+ LocaleManager.getLanguageName(mSelectedLanguage),
+ LocaleManager.getRegionName(mSelectedRegion));
+ }
+ }
+ } else {
+ // Require all strings to be translated? No, some of these may not
+ // be translatable (e.g. translatable=false, defined in donottranslate.xml, etc.)
+ //int missing = mTable.getItemCount() - mTranslations.values().size();
+ //if (missing > 0) {
+ // message = String.format("Missing %1$d translations", missing);
+ //}
+ }
+
+ boolean valid = message == null;
+ mTable.setEnabled(message == null);
+ mOkButton.setEnabled(valid);
+ showError(message);
+ }
+
+ private void showError(String error) {
+ GridData data = (GridData) mErrorPanel.getLayoutData();
+
+ boolean show = error != null;
+ if (show == data.exclude) {
+ if (show) {
+ if (mErrorLabel == null) {
+ mErrorPanel.setLayout(new GridLayout(2, false));
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ ISharedImages sharedImages = workbench.getSharedImages();
+ String iconName = ISharedImages.IMG_OBJS_ERROR_TSK;
+ Image image = sharedImages.getImage(iconName);
+ @SuppressWarnings("unused")
+ ImageControl icon = new ImageControl(mErrorPanel, SWT.NONE, image);
+
+ mErrorLabel = new Label(mErrorPanel, SWT.NONE);
+ mErrorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
+ 1, 1));
+ }
+ mErrorLabel.setText(error);
+ }
+ data.exclude = !show;
+ mErrorPanel.getParent().layout(true);
+ }
+ }
+
+ @Override
+ protected void okPressed() {
+ mTableViewer.applyEditorValue();
+
+ super.okPressed();
+ createTranslation();
+ }
+
+ // ---- Implements ControlListener ----
+
+ @Override
+ public void controlMoved(ControlEvent e) {
+ }
+
+ @Override
+ public void controlResized(ControlEvent e) {
+ if (mIgnore) {
+ return;
+ }
+
+ updateColumnWidths();
+ }
+
+ // ---- Implements SelectionListener ----
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (mIgnore) {
+ return;
+ }
+
+ Object source = e.getSource();
+ if (source == mLanguageCombo) {
+ try {
+ mIgnore = true;
+ mRegionCombo.select(0);
+ mSelectedRegion = null;
+ } finally {
+ mIgnore = false;
+ }
+
+ int languageIndex = mLanguageCombo.getSelectionIndex();
+ if (languageIndex == 0) {
+ mSelectedLanguage = null;
+ mRegionCombo.setEnabled(false);
+ } else {
+ // This depends on the label format
+ mSelectedLanguage = mLanguageCombo.getItem(languageIndex).substring(0, 2);
+ mRegionCombo.setEnabled(true);
+ }
+
+ updateTarget();
+ updateFlag();
+ } else if (source == mRegionCombo) {
+ int regionIndex = mRegionCombo.getSelectionIndex();
+ if (regionIndex == 0) {
+ mSelectedRegion = null;
+ } else {
+ mSelectedRegion = mRegionCombo.getItem(regionIndex).substring(0, 2);
+ }
+
+ updateTarget();
+ updateFlag();
+ }
+
+ try {
+ mIgnore = true;
+ validatePage();
+ } finally {
+ mIgnore = false;
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ // ---- TraverseListener ----
+
+ @Override
+ public void keyTraversed(TraverseEvent e) {
+ // If you press Return and we're not cell editing, start editing the current row
+ if (e.detail == SWT.TRAVERSE_RETURN && !mTableViewer.isCellEditorActive()) {
+ int index = mTable.getSelectionIndex();
+ if (index != -1) {
+ Object next = mTable.getItem(index).getData();
+ mTableViewer.editElement(next, NEW_TRANSLATION_COLUMN);
+ }
+ }
+ }
+
+ /** Editing support for the translation column */
+ private class TranslationEditingSupport extends EditingSupport {
+ /**
+ * When true, setValue is being called as part of a default action
+ * (e.g. Return), not due to focus loss
+ */
+ private boolean mDefaultAction;
+
+ private TranslationEditingSupport(ColumnViewer viewer) {
+ super(viewer);
+ }
+
+ @Override
+ protected void setValue(Object element, Object value) {
+ ResourceItem item = (ResourceItem) element;
+ mTranslations.put(item.getName(), value.toString());
+ mTableViewer.update(element, null);
+ validatePage();
+
+ // If the user is pressing Return to finish editing a value (which is
+ // not the only way this method can get called - for example, if you click
+ // outside the cell while editing, the focus loss will also result in
+ // this method getting called), then mDefaultAction is true, and we automatically
+ // start editing the next row.
+ if (mDefaultAction) {
+ mTable.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!mTable.isDisposed() && !mTableViewer.isCellEditorActive()) {
+ int index = mTable.getSelectionIndex();
+ if (index != -1 && index < mTable.getItemCount() - 1) {
+ Object next = mTable.getItem(index + 1).getData();
+ mTableViewer.editElement(next, NEW_TRANSLATION_COLUMN);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ ResourceItem item = (ResourceItem) element;
+ String value = mTranslations.get(item.getName());
+ if (value == null) {
+ return "";
+ }
+ return value;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ return new TextCellEditor(mTable) {
+ @Override
+ protected void handleDefaultSelection(SelectionEvent event) {
+ try {
+ mDefaultAction = true;
+ super.handleDefaultSelection(event);
+ } finally {
+ mDefaultAction = false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected boolean canEdit(Object element) {
+ return true;
+ }
+ }
+
+ private class MyTableViewer extends TableViewer {
+ public MyTableViewer(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ // Make this public so we can call it to ensure values are applied before the dialog
+ // is dismissed in {@link #okPressed}
+ @Override
+ public void applyEditorValue() {
+ super.applyEditorValue();
+ }
+ }
+}