diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java index 7a9f35224e6a..97289c509187 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CustomCodeStyleSettings; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent; import com.intellij.ui.treeStructure.treetable.ListTreeTableModel; import com.intellij.ui.treeStructure.treetable.TreeTable; import com.intellij.ui.treeStructure.treetable.TreeTableCellRenderer; @@ -602,34 +603,32 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle } } + /** + * @author Konstantin Bulenkov + */ private class MyValueEditor extends AbstractTableCellEditor { - private final JComboBox myComboBox = new JComboBox(); - private final JCheckBox myCheckBox = new JCheckBox(); + private final JCheckBox myBooleanEditor = new JCheckBox(); + private JBComboBoxTableCellEditorComponent myOptionsEditor = new JBComboBoxTableCellEditorComponent(); private Component myCurrentEditor = null; private MyTreeNode myCurrentNode = null; public MyValueEditor() { - ActionListener synchronizer = new ActionListener() { + myBooleanEditor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (myCurrentNode != null) { myCurrentNode.setValue(getCellEditorValue()); } } - }; - myComboBox.addActionListener(synchronizer); - myCheckBox.addActionListener(synchronizer); - - myComboBox.putClientProperty("JComponent.sizeVariant", "small"); - myComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); - myCheckBox.putClientProperty("JComponent.sizeVariant", "small"); + }); + myBooleanEditor.putClientProperty("JComponent.sizeVariant", "small"); } public Object getCellEditorValue() { - if (myCurrentEditor == myComboBox) { - return myComboBox.getSelectedItem(); + if (myCurrentEditor == myOptionsEditor) { + return myOptionsEditor.getEditorValue(); } - else if (myCurrentEditor == myCheckBox) { - return myCheckBox.isSelected() ? Boolean.TRUE : Boolean.FALSE; + else if (myCurrentEditor == myBooleanEditor) { + return myBooleanEditor.isSelected() ? Boolean.TRUE : Boolean.FALSE; } return null; @@ -642,27 +641,22 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle myCurrentNode = null; if (defaultNode instanceof MyTreeNode) { MyTreeNode node = (MyTreeNode)defaultNode; + myCurrentNode = node; if (node.getKey() instanceof BooleanOption) { - myCurrentEditor = myCheckBox; - myCheckBox.setSelected(node.getValue() == Boolean.TRUE); - myCheckBox.setEnabled(node.isEnabled()); + myCurrentEditor = myBooleanEditor; + myBooleanEditor.setSelected(node.getValue() == Boolean.TRUE); + myBooleanEditor.setEnabled(node.isEnabled()); } else { - myCurrentEditor = myComboBox; - myComboBox.removeAllItems(); - SelectionOption key = (SelectionOption)node.getKey(); - String[] values = key.options; - for (String value1 : values) { - myComboBox.addItem(value1); - } - myComboBox.setSelectedItem(node.getValue()); - myComboBox.setEnabled(node.isEnabled()); + myCurrentEditor = myOptionsEditor; + myOptionsEditor.setCell(table, row, column); + myOptionsEditor.setText(String.valueOf(node.getValue())); + myOptionsEditor.setOptions(((SelectionOption)node.getKey()).options); + myOptionsEditor.setDefaultValue(node.getValue()); } - myCurrentNode = node; } myCurrentEditor.setBackground(table.getBackground()); - return myCurrentEditor; } } diff --git a/platform/platform-api/src/com/intellij/ui/components/JBList.java b/platform/platform-api/src/com/intellij/ui/components/JBList.java index 71f523ac687f..0849651a54ed 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBList.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBList.java @@ -53,7 +53,7 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi init(); } - private static DefaultListModel createDefaultListModel(Object[] items) { + public static DefaultListModel createDefaultListModel(Object... items) { final DefaultListModel model = new DefaultListModel(); for (Object item : items) { model.add(model.getSize(), item); diff --git a/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java b/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java new file mode 100644 index 000000000000..45882aa40599 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * 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.intellij.ui.components.editors; + +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBList; + +import javax.swing.*; +import java.awt.*; + +/** + * Solves rendering problems in JTable components when JComboBox objects are used as cell + * editors components. Known issues of using JComboBox component are the following: + * 1. Ugly view if row height is small enough + * 2. Truncated strings in the combobox popup if column width is less than text value width + * + * @author Konstantin Bulenkov + */ +public class JBComboBoxTableCellEditorComponent extends JBLabel { + private JTable myTable; + private int myRow = 0; + private int myColumn = 0; + private final JBList myList = new JBList(); + private Object[] myOptions = {}; + private Object myValue; + private ListCellRenderer myRenderer; + + public JBComboBoxTableCellEditorComponent() { + } + + public JBComboBoxTableCellEditorComponent(JTable table) { + myTable = table; + } + + public void setTable(JTable table) { + myTable = table; + } + + public void setCell(JTable table, int row, int column) { + setTable(table); + setRow(row); + setColumn(column); + } + + public void setRow(int row) { + myRow = row; + } + + public void setColumn(int column) { + myColumn = column; + } + + public void setOptions(Object... options) { + myOptions = options; + } + + @Override + public void addNotify() { + super.addNotify(); + initAndShowPopup(); + } + + private void initAndShowPopup() { + myList.removeAll(); + final Rectangle rect = myTable.getCellRect(myRow, myColumn, true); + final Point point = new Point(rect.x, rect.y); + myList.setModel(JBList.createDefaultListModel(myOptions)); + if (myRenderer != null) { + myList.setCellRenderer(myRenderer); + } + JBPopupFactory.getInstance() + .createListPopupBuilder(myList) + .setItemChoosenCallback(new Runnable() { + @Override + public void run() { + myValue = myList.getSelectedValue(); + } + }).createPopup() + .show(new RelativePoint(myTable, point)); + } + + public Object getEditorValue() { + return myValue; + } + + public void setRenderer(ListCellRenderer renderer) { + myRenderer = renderer; + } + + public void setDefaultValue(Object value) { + myValue = value; + } +}