| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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.google.gct.testing; |
| |
| import com.android.annotations.Nullable; |
| import com.android.tools.analytics.UsageTracker; |
| import com.google.common.cache.CacheBuilder; |
| import com.google.common.cache.CacheLoader; |
| import com.google.common.cache.LoadingCache; |
| import com.google.gct.testing.android.CloudConfiguration; |
| import com.google.gct.testing.dimension.ConfigurationChangeEvent; |
| import com.google.gct.testing.dimension.ConfigurationChangeListener; |
| import com.google.wireless.android.sdk.stats.AndroidStudioEvent; |
| import com.google.wireless.android.sdk.stats.AndroidStudioEvent.EventCategory; |
| import com.google.wireless.android.sdk.stats.AndroidStudioEvent.EventKind; |
| import com.intellij.execution.ExecutionBundle; |
| import com.intellij.icons.AllIcons; |
| import com.intellij.openapi.actionSystem.AnAction; |
| import com.intellij.openapi.actionSystem.AnActionEvent; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.ui.Splitter; |
| import com.intellij.ui.*; |
| import com.intellij.ui.treeStructure.Tree; |
| import com.intellij.util.IconUtil; |
| import com.intellij.util.PlatformIcons; |
| import com.intellij.util.ui.UIUtil; |
| import com.intellij.util.ui.tree.TreeUtil; |
| import icons.AndroidIcons; |
| import org.jetbrains.android.facet.AndroidFacet; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.swing.*; |
| import javax.swing.event.DocumentEvent; |
| import javax.swing.event.TreeSelectionEvent; |
| import javax.swing.event.TreeSelectionListener; |
| import javax.swing.tree.*; |
| import java.awt.*; |
| import java.awt.event.FocusEvent; |
| import java.awt.event.FocusListener; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.ExecutionException; |
| |
| import static com.google.gct.testing.CloudTestingUtils.createConfigurationChooserGbc; |
| |
| public class CloudConfigurationChooserDialog extends DialogWrapper implements ConfigurationChangeListener { |
| |
| private final List<CloudConfigurationImpl> editableConfigurations; |
| private final List<CloudConfigurationImpl> defaultConfigurations; |
| private final MyAddAction myAddAction = new MyAddAction(); |
| private final MyRemoveAction myRemoveAction = new MyRemoveAction(); |
| private final MyCopyActionButton myCopyActionButton = new MyCopyActionButton(); |
| private final MyMoveUpAction myMoveUpAction = new MyMoveUpAction(); |
| private final MyMoveDownAction myMoveDownAction = new MyMoveDownAction(); |
| |
| private final DefaultMutableTreeNode customRoot = new DefaultMutableTreeNode("Custom"); |
| private final DefaultMutableTreeNode defaultsRoot = new DefaultMutableTreeNode("Defaults"); |
| |
| private final CloudConfiguration.Kind configurationKind; |
| |
| private JPanel myPanel; |
| private final Splitter mySplitter = new Splitter(false); |
| private JPanel myConfigurationPanel; |
| private JTextField myConfigurationName; |
| private Tree myConfigurationTree; |
| private JPanel myConfigurationTreePanel; |
| private JLabel myConfigurationNameLabel; |
| private JLabel myGroupDescriptionLabel; |
| private JPanel myConfigurationEditorPanel; |
| private JPanel myConfigurationInfoPanel; |
| private JLabel myConfigurationInfoLabel; |
| private JLabel myDimensionNameLabel; |
| |
| private ToolbarDecorator myToolbarDecorator; |
| |
| // The configuration that is currently selected in the tree |
| @Nullable |
| private CloudConfigurationImpl selectedConfiguration; |
| |
| private final AndroidFacet facet; |
| |
| public CloudConfigurationChooserDialog(Module module, |
| List<CloudConfigurationImpl> editableConfigurations, |
| List<CloudConfigurationImpl> defaultConfigurations, |
| @Nullable final CloudConfigurationImpl initiallySelectedConfiguration, |
| @NotNull CloudConfiguration.Kind configurationKind) { |
| |
| super(module.getProject(), true); |
| |
| this.configurationKind = configurationKind; |
| |
| myConfigurationInfoPanel.setPreferredSize(new Dimension(490, UIUtil.isUnderDarcula() ? 153 : 156)); |
| // Note that we are editing the list we were given. |
| // This could be dangerous. |
| this.editableConfigurations = editableConfigurations; |
| this.defaultConfigurations = defaultConfigurations; |
| |
| facet = AndroidFacet.getInstance(module); |
| |
| if (configurationKind == CloudConfiguration.Kind.SINGLE_DEVICE) { |
| setTitle("Single Device Configurations"); |
| |
| UsageTracker.getInstance().log(AndroidStudioEvent.newBuilder() |
| .setCategory(EventCategory.CLOUD_TESTING) |
| .setKind(EventKind.CLOUD_TESTING_CONFIGURE_CLOUD_DEVICE)); |
| |
| } else { |
| setTitle("Matrix Configurations"); |
| UsageTracker.getInstance().log(AndroidStudioEvent.newBuilder() |
| .setCategory(EventCategory.CLOUD_TESTING) |
| .setKind(EventKind.CLOUD_TESTING_CONFIGURE_MATRIX)); |
| } |
| |
| getOKAction().setEnabled(true); |
| |
| myConfigurationTree.addTreeSelectionListener(new TreeSelectionListener() { |
| @Override |
| public void valueChanged(TreeSelectionEvent e) { |
| |
| TreePath selectedPath = e.getPath(); |
| if (selectedPath.getPathCount() == 2) { |
| updateConfigurationControls(false); |
| DefaultMutableTreeNode selectedGroup = (DefaultMutableTreeNode)selectedPath.getPath()[1]; |
| if (selectedGroup.equals(customRoot)) { |
| myGroupDescriptionLabel.setText("User-defined configurations. To add a new one click "); |
| myGroupDescriptionLabel.setIcon(IconUtil.getAddIcon()); |
| myGroupDescriptionLabel.setHorizontalTextPosition(SwingConstants.LEFT); |
| } else { |
| myGroupDescriptionLabel.setText("Default configurations"); |
| myGroupDescriptionLabel.setIcon(null); |
| } |
| selectedConfiguration = null; |
| } else { |
| updateConfigurationControls(true); |
| selectedConfiguration = (CloudConfigurationImpl) ((DefaultMutableTreeNode)selectedPath.getPath()[2]).getUserObject(); |
| myConfigurationName.setText(selectedConfiguration.getName()); |
| myConfigurationName.setEnabled(selectedConfiguration.isEditable()); |
| } |
| updateConfigurationDetailsPanel(selectedConfiguration); |
| } |
| }); |
| myConfigurationTree.addFocusListener(new FocusListener() { |
| @Override |
| public void focusGained(FocusEvent e) { |
| myDimensionNameLabel.setText(""); |
| myConfigurationInfoLabel.setText(""); |
| } |
| |
| @Override |
| public void focusLost(FocusEvent e) { |
| //ignore |
| } |
| }); |
| myConfigurationTree.setCellRenderer(new ColoredTreeCellRenderer() { |
| |
| @Override |
| public void customizeCellRenderer(@NotNull JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, |
| boolean hasFocus) { |
| if (value instanceof DefaultMutableTreeNode) { |
| final DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; |
| |
| if (node == customRoot) { |
| append("Custom", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); |
| setIcon(AndroidIcons.Android); |
| } else if (node == defaultsRoot) { |
| append("Defaults", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); |
| setIcon(AllIcons.General.Settings); |
| } else if (node.getUserObject() instanceof CloudConfigurationImpl) { |
| CloudConfigurationImpl config = (CloudConfigurationImpl) node.getUserObject(); |
| boolean isInvalidConfiguration = config.getDeviceConfigurationCount() < 1; |
| boolean oldMySelected = mySelected; |
| // This is a trick to avoid using white color for the selected element if it has to be red. |
| if (isInvalidConfiguration) { |
| mySelected = false; |
| } |
| append(config.getDisplayName(), isInvalidConfiguration |
| ? new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, JBColor.RED) |
| : SimpleTextAttributes.REGULAR_ATTRIBUTES); |
| mySelected = oldMySelected; |
| setIcon(config.getIcon()); |
| } |
| |
| setIconTextGap(2); |
| } |
| } |
| }); |
| |
| //Disposer.register(myDisposable, ???); |
| |
| if (initiallySelectedConfiguration != null) { |
| myConfigurationName.setText(initiallySelectedConfiguration.getName()); |
| } |
| |
| myConfigurationName.getDocument().addDocumentListener(new DocumentAdapter() { |
| @Override |
| protected void textChanged(DocumentEvent e) { |
| selectedConfiguration.setName(myConfigurationName.getText()); |
| } |
| }); |
| |
| myDimensionNameLabel = new JLabel("", SwingConstants.LEFT); |
| Font currentFont = myDimensionNameLabel.getFont(); |
| myDimensionNameLabel.setFont(new Font(currentFont.getFontName(), Font.BOLD, currentFont.getSize())); |
| myConfigurationInfoPanel.add(myDimensionNameLabel, createConfigurationChooserGbc(0, 0)); |
| myConfigurationInfoLabel = new JLabel("", SwingConstants.LEFT); |
| myConfigurationInfoPanel.add(myConfigurationInfoLabel, createConfigurationChooserGbc(0, 1)); |
| |
| DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Root"); |
| DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); |
| myConfigurationTree.setModel(treeModel); |
| myConfigurationTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); |
| treeModel.insertNodeInto(customRoot, rootNode, 0); |
| treeModel.insertNodeInto(defaultsRoot, rootNode, 1); |
| selectTreeNode(customRoot); |
| for (CloudConfigurationImpl configuration : editableConfigurations) { |
| addConfigurationToTree(-1, configuration, configuration.equals(initiallySelectedConfiguration)); |
| } |
| for (CloudConfigurationImpl configuration : defaultConfigurations) { |
| addConfigurationToTree(-1, configuration, configuration.equals(initiallySelectedConfiguration)); |
| } |
| |
| Dimension preferredSize = myConfigurationTreePanel.getPreferredSize(); |
| preferredSize.width = Math.max(preferredSize.width, 350); |
| preferredSize.height = Math.max(preferredSize.height, 440); |
| myConfigurationTreePanel.setPreferredSize(preferredSize); |
| myConfigurationTreePanel.add(createLeftPanel(), BorderLayout.CENTER); |
| |
| mySplitter.setProportion(0.35f); |
| |
| mySplitter.setFirstComponent(myConfigurationTreePanel); |
| mySplitter.setSecondComponent(myConfigurationPanel); |
| myPanel.add(mySplitter, BorderLayout.CENTER); |
| |
| treeModel.reload(); |
| |
| expandAllRows(myConfigurationTree); |
| |
| init(); |
| } |
| |
| /** |
| * Adds the given configuration to the appropriate place in the tree and selects it if desired. |
| */ |
| private void addConfigurationToTree(int index, CloudConfigurationImpl configuration, boolean makeSelected) { |
| configuration.addConfigurationChangeListener(this); |
| |
| final DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(configuration); |
| if (configuration.isEditable()) { |
| addChildToNode(index, newChild, customRoot); |
| } else { |
| addChildToNode(index, newChild, defaultsRoot); |
| } |
| |
| if (makeSelected) { |
| selectTreeNode(newChild); |
| } |
| } |
| |
| private void addChildToNode(int index, DefaultMutableTreeNode child, DefaultMutableTreeNode node) { |
| if (index == -1) { |
| node.add(child); |
| } else { |
| node.insert(child, index); |
| } |
| } |
| |
| private void selectTreeNode(final DefaultMutableTreeNode node) { |
| SwingUtilities.invokeLater(new Runnable() { |
| @Override |
| public void run() { |
| TreeUtil.selectInTree(node, true, myConfigurationTree); |
| } |
| }); |
| } |
| |
| /** |
| * Removes the given configuration from the tree. We only look under the custom root. |
| */ |
| private void removeConfigurationFromTree(CloudConfigurationImpl configuration) { |
| configuration.removeConfigurationChangeListener(this); |
| MutableTreeNode toRemove = (MutableTreeNode) TreeUtil.findNodeWithObject(configuration, myConfigurationTree.getModel(), customRoot); |
| customRoot.remove(toRemove); |
| } |
| |
| private JPanel createLeftPanel() { |
| myToolbarDecorator = ToolbarDecorator.createDecorator(myConfigurationTree).setAsUsualTopToolbar() |
| .setAddAction(myAddAction).setAddActionUpdater(myAddAction).setAddActionName( |
| ExecutionBundle.message("add.new.run.configuration.action2.name")) |
| .setRemoveAction(myRemoveAction).setRemoveActionUpdater(myRemoveAction).setRemoveActionName( |
| ExecutionBundle.message("remove.run.configuration.action.name")) |
| .setMoveUpAction(myMoveUpAction).setMoveUpActionUpdater(myMoveUpAction).setMoveUpActionName( |
| ExecutionBundle.message("move.up.action.name")) |
| .setMoveDownAction(myMoveDownAction).setMoveDownActionUpdater(myMoveDownAction).setMoveDownActionName( |
| ExecutionBundle.message("move.down.action.name")) |
| .addExtraAction(myCopyActionButton) |
| //.addExtraAction(AnActionButton.fromAction(new MySaveAction())) |
| .setButtonComparator(ExecutionBundle.message("add.new.run.configuration.action2.name"), |
| ExecutionBundle.message("remove.run.configuration.action.name"), |
| ExecutionBundle.message("copy.configuration.action.name"), |
| ExecutionBundle.message("action.name.save.configuration"), |
| ExecutionBundle.message("run.configuration.edit.default.configuration.settings.text"), |
| ExecutionBundle.message("move.up.action.name"), ExecutionBundle.message("move.down.action.name"), |
| ExecutionBundle.message("run.configuration.create.folder.text")).setForcedDnD(); |
| return myToolbarDecorator.createPanel(); |
| } |
| |
| LoadingCache<CloudConfigurationImpl, TwoPanelTree> dimensionTreeCache = CacheBuilder.newBuilder() |
| .build(new CacheLoader<CloudConfigurationImpl, TwoPanelTree>() { |
| @Override |
| public TwoPanelTree load(CloudConfigurationImpl configuration) throws Exception { |
| final TwoPanelTree tree = new TwoPanelTree(configuration); |
| final TwoPanelTreeSelectionListener treeSelectionListener = new TwoPanelTreeSelectionListener() { |
| @Override |
| public void dimensionSelectionChanged(TwoPanelTreeDimensionSelectionEvent e) { |
| myDimensionNameLabel.setText(""); |
| myConfigurationInfoLabel.setText(""); |
| } |
| |
| @Override |
| public void typeSelectionChanged(TwoPanelTreeTypeSelectionEvent e) { |
| myDimensionNameLabel.setText(e.getType().getConfigurationDialogDisplayName()); |
| String details = "<html><table cellpadding='0'>"; |
| for (Map.Entry<String, String> entry : e.getType().getDetails().entrySet()) { |
| details += "<tr><td>" + entry.getKey() + ": </td><td>" + entry.getValue() + "</td></tr>"; |
| } |
| details += "</table>"; |
| if (!e.getCurrentDimension().getSupportedDomain().contains(e.getType())) { |
| details += "<br><i>This option is not currently supported by Google Cloud.</i>"; |
| } |
| details += "</html>"; |
| myConfigurationInfoLabel.setText(details); |
| } |
| |
| @Override |
| public void groupSelectionChanged(TwoPanelTreeTypeGroupSelectionEvent e) { |
| myDimensionNameLabel.setText(e.getGroup().getDescription()); |
| myConfigurationInfoLabel.setText(""); |
| } |
| }; |
| |
| tree.addSelectionListener(treeSelectionListener); |
| return tree; |
| } |
| }); |
| |
| |
| private void updateConfigurationDetailsPanel(CloudConfigurationImpl configuration) { |
| |
| myConfigurationEditorPanel.removeAll(); |
| |
| if (configuration != null) { |
| myConfigurationInfoPanel.setVisible(true); |
| try { |
| myConfigurationEditorPanel.add(dimensionTreeCache.get(configuration).getPanel()); |
| } |
| catch (ExecutionException e) { |
| e.printStackTrace(); |
| } |
| myConfigurationEditorPanel.updateUI(); |
| } else { |
| myConfigurationInfoPanel.setVisible(false); |
| } |
| } |
| |
| private void updateConfigurationControls(boolean isRealConfiguration) { |
| myConfigurationName.setVisible(isRealConfiguration); |
| myConfigurationNameLabel.setVisible(isRealConfiguration); |
| myGroupDescriptionLabel.setVisible(!isRealConfiguration); |
| } |
| |
| private void expandAllRows(Tree tree) { |
| for (int i = 0; i < tree.getRowCount(); i++) { |
| tree.expandRow(i); |
| } |
| } |
| |
| @Nullable |
| public CloudConfigurationImpl getSelectedConfiguration() { |
| return selectedConfiguration; |
| } |
| |
| @Override |
| public JComponent getPreferredFocusedComponent() { |
| return myConfigurationTree; |
| } |
| |
| @Override |
| protected JComponent createCenterPanel() { |
| return myPanel; |
| } |
| |
| private void createUIComponents() { |
| // TODO: place custom component creation code here |
| } |
| |
| @Override |
| public void configurationChanged(ConfigurationChangeEvent e) { |
| DefaultTreeModel model = (DefaultTreeModel)myConfigurationTree.getModel(); |
| model.nodeChanged(TreeUtil.findNodeWithObject(e.getConfiguration(), model, customRoot)); |
| myConfigurationTreePanel.updateUI(); |
| } |
| |
| private class MyRemoveAction extends AnAction implements AnActionButtonRunnable, AnActionButtonUpdater { |
| |
| @Override |
| public void actionPerformed(AnActionEvent e) { |
| doRemove(); |
| } |
| |
| @Override |
| public void run(AnActionButton button) { |
| doRemove(); |
| } |
| |
| private void doRemove() { |
| if (selectedConfiguration == null || !selectedConfiguration.isEditable()) { |
| // TODO: This button should be disabled in these cases |
| return; |
| } |
| |
| int removedIndex = editableConfigurations.indexOf(selectedConfiguration); |
| editableConfigurations.remove(selectedConfiguration); |
| removeConfigurationFromTree(selectedConfiguration); |
| |
| DefaultMutableTreeNode treeNode; |
| if (editableConfigurations.isEmpty()) { |
| if (defaultConfigurations.isEmpty()) { |
| treeNode = customRoot; |
| } else { |
| treeNode = TreeUtil.findNodeWithObject(defaultsRoot, defaultConfigurations.get(0)); |
| } |
| } else { |
| if (removedIndex > editableConfigurations.size() - 1) { |
| removedIndex = editableConfigurations.size() - 1; |
| } |
| treeNode = TreeUtil.findNodeWithObject(customRoot, editableConfigurations.get(removedIndex)); |
| } |
| selectTreeNode(treeNode); |
| |
| updateConfigurationTree(); |
| } |
| |
| @Override |
| public boolean isEnabled(AnActionEvent e) { |
| return selectedConfiguration != null && selectedConfiguration.isEditable(); |
| } |
| } |
| |
| private class MyCopyActionButton extends AnActionButton implements AnActionButtonUpdater { |
| |
| public MyCopyActionButton() { |
| super(ExecutionBundle.message("copy.configuration.action.name"), ExecutionBundle.message("copy.configuration.action.name"), |
| PlatformIcons.COPY_ICON); |
| addCustomUpdater(this); |
| } |
| |
| @Override |
| public void actionPerformed(AnActionEvent e) { |
| // selectedConfiguration should not be null here, but handle this scenario just in case. |
| CloudConfigurationImpl newConfiguration = selectedConfiguration != null |
| ? selectedConfiguration.copy("Copy of ") |
| : new CloudConfigurationImpl(facet, configurationKind); |
| |
| addNewConfiguration(newConfiguration); |
| } |
| |
| @Override |
| public boolean isEnabled(AnActionEvent e) { |
| return selectedConfiguration != null; |
| } |
| } |
| |
| private class MyAddAction extends AnAction implements AnActionButtonRunnable, AnActionButtonUpdater { |
| |
| @Override |
| public void actionPerformed(AnActionEvent e) { |
| doAdd(); |
| } |
| |
| @Override |
| public void run(AnActionButton button) { |
| doAdd(); |
| } |
| |
| private void doAdd() { |
| addNewConfiguration(new CloudConfigurationImpl(facet, configurationKind)); |
| } |
| |
| @Override |
| public boolean isEnabled(AnActionEvent e) { |
| return true; |
| } |
| } |
| |
| private void addNewConfiguration(CloudConfigurationImpl newConfiguration) { |
| newConfiguration.setIcon(CloudConfigurationHelper.DEFAULT_ICON); |
| int addIndex = selectedConfiguration == null |
| ? editableConfigurations.size() |
| : editableConfigurations.indexOf(selectedConfiguration) + 1; |
| editableConfigurations.add(addIndex, newConfiguration); |
| addConfigurationToTree(addIndex, newConfiguration, true); |
| selectedConfiguration = newConfiguration; |
| |
| updateConfigurationTree(); |
| } |
| |
| private class MyMoveUpAction extends AnAction implements AnActionButtonRunnable, AnActionButtonUpdater { |
| |
| @Override |
| public void actionPerformed(AnActionEvent e) { |
| moveUp(); |
| } |
| |
| @Override |
| public void run(AnActionButton button) { |
| moveUp(); |
| } |
| |
| private void moveUp() { |
| if (selectedConfiguration != null) { |
| int index = editableConfigurations.indexOf(selectedConfiguration); |
| if (index > 0) { |
| moveConfigurationToIndex(index - 1, selectedConfiguration); |
| } |
| } |
| } |
| |
| @Override |
| public boolean isEnabled(AnActionEvent e) { |
| return selectedConfiguration != null |
| && selectedConfiguration.isEditable() |
| && editableConfigurations.indexOf(selectedConfiguration) > 0; |
| } |
| } |
| |
| private class MyMoveDownAction extends AnAction implements AnActionButtonRunnable, AnActionButtonUpdater { |
| |
| @Override |
| public void actionPerformed(AnActionEvent e) { |
| moveDown(); |
| } |
| |
| @Override |
| public void run(AnActionButton button) { |
| moveDown(); |
| } |
| |
| private void moveDown() { |
| if (selectedConfiguration != null) { |
| int index = editableConfigurations.indexOf(selectedConfiguration); |
| if (index != -1 && index < editableConfigurations.size() - 1) { |
| moveConfigurationToIndex(index + 1, selectedConfiguration); |
| } |
| } |
| } |
| |
| @Override |
| public boolean isEnabled(AnActionEvent e) { |
| return selectedConfiguration != null |
| && selectedConfiguration.isEditable() |
| && editableConfigurations.indexOf(selectedConfiguration) < editableConfigurations.size() - 1; |
| } |
| } |
| |
| private void moveConfigurationToIndex(int index, CloudConfigurationImpl configuration) { |
| editableConfigurations.remove(configuration); |
| editableConfigurations.add(index, configuration); |
| removeConfigurationFromTree(configuration); |
| addConfigurationToTree(index, configuration, true); |
| updateConfigurationTree(); |
| } |
| |
| private void updateConfigurationTree() { |
| ((DefaultTreeModel) myConfigurationTree.getModel()).reload(); |
| expandAllRows(myConfigurationTree); |
| myConfigurationTree.updateUI(); |
| } |
| |
| @Override |
| protected void doOKAction() { |
| super.doOKAction(); |
| } |
| } |