| /* |
| * 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(); |
| } |
| } |
| } |