Java tutorial
/* * Copyright 2000-2012 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.compiler.impl.javaCompiler; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.*; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import javax.swing.DefaultCellEditor; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.plaf.basic.BasicComboBoxEditor; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import org.jetbrains.annotations.Nullable; import com.intellij.icons.AllIcons; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.configuration.ChooseModulesDialog; import com.intellij.openapi.ui.ComboBox; import com.intellij.ui.AnActionButton; import com.intellij.ui.AnActionButtonRunnable; import com.intellij.ui.JBColor; import com.intellij.ui.TableUtil; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.table.JBTable; import com.intellij.util.ui.ItemRemovable; import lombok.val; /** * @author Eugene Zhuravlev * Date: 5/9/12 */ public class TargetOptionsComponent extends JPanel { private static final class TargetLevelTableModel extends AbstractTableModel implements ItemRemovable { private static final class Item { final Module module; String targetLevel = ""; Item(Module module) { this.module = module; } Item(Module module, String targetLevel) { this.module = module; this.targetLevel = targetLevel; } } private final List<Item> myItems = new ArrayList<Item>(); @Override public int getRowCount() { return myItems.size(); } @Override public int getColumnCount() { return 2; } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex != 0; } @Override public Object getValueAt(int rowIndex, int columnIndex) { final Item item = myItems.get(rowIndex); return columnIndex == 0 ? item.module : item.targetLevel; } //public void addItem(Module module) { // final int size = myItems.size(); // myItems.add(new Item(module.getName())); // fireTableRowsInserted(size, size); //} @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { final Item item = myItems.get(rowIndex); item.targetLevel = ((String) aValue).trim(); fireTableCellUpdated(rowIndex, columnIndex); } public void addItems(Collection<Module> modules) { for (Module module : modules) { myItems.add(new Item(module)); } sorItems(); fireTableDataChanged(); } private void sorItems() { Collections.sort(myItems, new Comparator<Item>() { @Override public int compare(Item o1, Item o2) { return o1.module.getName().compareTo(o2.module.getName()); } }); } public List<Item> getItems() { return myItems; } public void setItems(Map<Module, String> items) { myItems.clear(); for (Map.Entry<Module, String> entry : items.entrySet()) { myItems.add(new Item(entry.getKey(), entry.getValue())); } sorItems(); fireTableDataChanged(); } @Override public void removeRow(int idx) { myItems.remove(idx); } } private static final class TargetLevelComboboxModel extends AbstractListModel implements ComboBoxModel { private final List<String> myOptions = new ArrayList<String>(); private String mySelectedItem = ""; TargetLevelComboboxModel() { //myOptions.add(""); for (int i = KNOWN_TARGETS.length - 1; i >= 0; i--) { myOptions.add(KNOWN_TARGETS[i]); } } @Override public int getSize() { return myOptions.size(); } @Override public Object getSelectedItem() { return mySelectedItem; } @Override public void setSelectedItem(Object anItem) { mySelectedItem = toModelItem((String) anItem); fireContentsChanged(this, 0, myOptions.size()); } @Override public Object getElementAt(int index) { return myOptions.get(index); } private String toModelItem(String item) { item = item.trim(); for (String option : myOptions) { if (option.equals(item)) { return option; } } return item; } } private static class ModuleCellRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { try { return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } finally { final Module module = (Module) value; setText(module.getName()); setIcon(AllIcons.Nodes.Module); } } } private static class TargetLevelCellEditor extends DefaultCellEditor { private TargetLevelCellEditor() { super(createTargetOptionsCombo()); setClickCountToStart(0); } } private static class TargetLevelCellRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (component instanceof JLabel) { final JLabel comp = (JLabel) component; comp.setHorizontalAlignment(SwingConstants.CENTER); if ("".equals(value)) { comp.setForeground(JBColor.GRAY); comp.setText(COMPILER_DEFAULT); } else { comp.setForeground(table.getForeground()); } } return component; } } static class HintTextField extends JTextField { private final char[] myHint; public HintTextField(final String hint) { this(hint, 0); } public HintTextField(final String hint, final int columns) { super(hint, columns); myHint = hint.toCharArray(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); final boolean isFocused = isFocusOwner(); if (!isFocused && getText().isEmpty()) { final Color oldColor = g.getColor(); final Font oldFont = g.getFont(); try { g.setColor(JBColor.GRAY); //g.setFont(oldFont.deriveFont(Font.ITALIC)); final FontMetrics metrics = g.getFontMetrics(); int x = Math.abs(getWidth() - metrics.charsWidth(myHint, 0, myHint.length)) / 2; int y = Math.abs(getHeight() - metrics.getHeight()) / 2 + metrics.getAscent(); g.drawChars(myHint, 0, myHint.length, x, y); } finally { g.setColor(oldColor); g.setFont(oldFont); } } } } private static final String[] KNOWN_TARGETS = new String[] { "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9" }; private static final String COMPILER_DEFAULT = "JDK default"; private final Project myProject; private ComboBox myCbProjectTargetLevel; private JBTable myTable; public TargetOptionsComponent(Project project) { super(new GridBagLayout()); myProject = project; //setBorder(BorderFactory.createTitledBorder("Bytecode target level")); myCbProjectTargetLevel = createTargetOptionsCombo(); myTable = new JBTable(new TargetLevelTableModel()); myTable.setRowHeight(22); myTable.getEmptyText().setText("All modules will be compiled with project bytecode version"); final TableColumn moduleColumn = myTable.getColumnModel().getColumn(0); moduleColumn.setHeaderValue("Module"); moduleColumn.setCellRenderer(new ModuleCellRenderer()); final TableColumn targetLevelColumn = myTable.getColumnModel().getColumn(1); final String columnTitle = "Target bytecode version"; targetLevelColumn.setHeaderValue(columnTitle); targetLevelColumn.setCellEditor(new TargetLevelCellEditor()); targetLevelColumn.setCellRenderer(new TargetLevelCellRenderer()); final int width = myTable.getFontMetrics(myTable.getFont()).stringWidth(columnTitle) + 10; targetLevelColumn.setPreferredWidth(width); targetLevelColumn.setMinWidth(width); targetLevelColumn.setMaxWidth(width); add(new JLabel("Project bytecode version (leave blank for jdk default): "), constraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NONE)); add(myCbProjectTargetLevel, constraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NONE)); add(new JLabel("Per-module bytecode version:"), constraints(0, 1, 2, 1, 1.0, 0.0, GridBagConstraints.NONE)); final JPanel tableComp = ToolbarDecorator.createDecorator(myTable).disableUpAction().disableDownAction() .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton anActionButton) { addModules(); } }).setRemoveAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton anActionButton) { removeSelectedModules(); } }).createPanel(); tableComp.setPreferredSize(new Dimension(myTable.getWidth(), 150)); add(tableComp, constraints(0, 2, 2, 1, 1.0, 1.0, GridBagConstraints.BOTH)); } private static GridBagConstraints constraints(final int gridx, final int gridy, final int gridwidth, final int gridheight, final double weightx, final double weighty, final int fill) { return new GridBagConstraints(gridx, gridy, gridwidth, gridheight, weightx, weighty, GridBagConstraints.WEST, fill, new Insets(5, 5, 0, 0), 0, 0); } private static ComboBox createTargetOptionsCombo() { final ComboBox combo = new ComboBox(new TargetLevelComboboxModel()); //combo.setRenderer(new DefaultListCellRenderer() { // @Override // public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { // try { // return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); // } // finally { // //if ("".equals(value)) { // // setText(COMPILER_DEFAULT); // //} // } // } //}); combo.setEditable(true); combo.setEditor(new BasicComboBoxEditor() { @Override protected JTextField createEditorComponent() { return new HintTextField(COMPILER_DEFAULT, 10); } }); return combo; } private void removeSelectedModules() { val rows = myTable.getSelectedRows(); if (rows.length > 0) { TableUtil.removeSelectedItems(myTable); } } private void addModules() { val model = (TargetLevelTableModel) myTable.getModel(); val items = new ArrayList<Module>(Arrays.asList(ModuleManager.getInstance(myProject).getModules())); Set<Module> alreadyAdded = new HashSet<Module>(); for (TargetLevelTableModel.Item item : model.getItems()) { alreadyAdded.add(item.module); } for (Iterator<Module> it = items.iterator(); it.hasNext();) { Module module = it.next(); if (alreadyAdded.contains(module)) { it.remove(); } } Collections.sort(items, new Comparator<Module>() { @Override public int compare(Module o1, Module o2) { return o1.getName().compareTo(o2.getName()); } }); val chooser = new ChooseModulesDialog(this, items, "Choose module"); chooser.show(); val elements = chooser.getChosenElements(); if (!elements.isEmpty()) { model.addItems(elements); } } public void setProjectBytecodeTargetLevel(String level) { myCbProjectTargetLevel.setSelectedItem(level == null ? "" : level); } @Nullable public String getProjectBytecodeTarget() { val item = ((String) myCbProjectTargetLevel.getSelectedItem()).trim(); return "".equals(item) ? null : item; } public Map<String, String> getModulesBytecodeTargetMap() { TargetLevelTableModel model = (TargetLevelTableModel) myTable.getModel(); val map = new HashMap<String, String>(); for (TargetLevelTableModel.Item item : model.getItems()) { map.put(item.module.getName(), item.targetLevel); } return map; } public void setModuleTargetLevels(Map<String, String> moduleLevels) { val map = new HashMap<Module, String>(); for (val module : ModuleManager.getInstance(myProject).getModules()) { val target = moduleLevels.get(module.getName()); if (target != null) { map.put(module, target); } } ((TargetLevelTableModel) myTable.getModel()).setItems(map); } }