path variables: alphanumerics, dots, underscores & minuses are allowed in macro names
[fedora-idea.git] / platform / platform-impl / src / com / intellij / application / options / pathMacros / PathMacroTable.java
blob74427f219f21095861a0b40dc021d08a4cd80780
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.application.options.pathMacros;
18 import com.intellij.application.options.PathMacrosCollector;
19 import com.intellij.openapi.application.ApplicationBundle;
20 import com.intellij.openapi.application.PathMacros;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.ui.Messages;
23 import com.intellij.openapi.util.Pair;
24 import com.intellij.openapi.util.text.StringUtil;
25 import com.intellij.util.ui.Table;
27 import javax.swing.*;
28 import javax.swing.table.AbstractTableModel;
29 import javax.swing.table.DefaultTableCellRenderer;
30 import javax.swing.table.TableColumn;
31 import java.awt.*;
32 import java.io.File;
33 import java.util.*;
34 import java.util.List;
35 import java.util.regex.Pattern;
37 /**
38 * @author dsl
40 public class PathMacroTable extends Table {
41 private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.pathMacros.PathMacroTable");
42 private final PathMacros myPathMacros = PathMacros.getInstance();
43 private final MyTableModel myTableModel = new MyTableModel();
44 private static final int NAME_COLUMN = 0;
45 private static final int VALUE_COLUMN = 1;
47 private final List<Pair<String, String>> myMacros = new ArrayList<Pair<String, String>>();
48 private static final Comparator<Pair<String, String>> MACRO_COMPARATOR = new Comparator<Pair<String, String>>() {
49 public int compare(Pair<String, String> pair, Pair<String, String> pair1) {
50 return pair.getFirst().compareTo(pair1.getFirst());
54 private final Collection<String> myUndefinedMacroNames;
56 public PathMacroTable() {
57 this(null);
60 public PathMacroTable(final Collection<String> undefinedMacroNames) {
61 myUndefinedMacroNames = undefinedMacroNames;
62 setModel(myTableModel);
63 TableColumn column = getColumnModel().getColumn(NAME_COLUMN);
64 column.setCellRenderer(new DefaultTableCellRenderer() {
65 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
66 final Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
67 final String macroValue = getMacroValueAt(row);
68 component.setForeground(macroValue.length() == 0
69 ? Color.RED
70 : isSelected ? table.getSelectionForeground() : table.getForeground());
71 return component;
73 });
74 setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
75 //obtainData();
78 public String getMacroValueAt(int row) {
79 return (String) getValueAt(row, VALUE_COLUMN);
82 public String getMacroNameAt(int row) {
83 return (String)getValueAt(row, NAME_COLUMN);
86 public void addMacro() {
87 final String title = ApplicationBundle.message("title.add.variable");
88 final PathMacroEditor macroEditor = new PathMacroEditor(title, "", "", new AddValidator(title));
89 macroEditor.show();
90 if (macroEditor.isOK()) {
91 final String name = macroEditor.getName();
92 myMacros.add(new Pair<String, String>(name, macroEditor.getValue()));
93 Collections.sort(myMacros, MACRO_COMPARATOR);
94 final int index = indexOfMacroWithName(name);
95 LOG.assertTrue(index >= 0);
96 myTableModel.fireTableDataChanged();
97 setRowSelectionInterval(index, index);
101 private boolean isValidRow(int selectedRow) {
102 return selectedRow >= 0 && selectedRow < myMacros.size();
105 public void removeSelectedMacros() {
106 final int[] selectedRows = getSelectedRows();
107 if(selectedRows.length == 0) return;
108 Arrays.sort(selectedRows);
109 final int originalRow = selectedRows[0];
110 for (int i = selectedRows.length - 1; i >= 0; i--) {
111 final int selectedRow = selectedRows[i];
112 if (isValidRow(selectedRow)) {
113 myMacros.remove(selectedRow);
116 myTableModel.fireTableDataChanged();
117 if (originalRow < getRowCount()) {
118 setRowSelectionInterval(originalRow, originalRow);
119 } else if (getRowCount() > 0) {
120 final int index = getRowCount() - 1;
121 setRowSelectionInterval(index, index);
125 public void commit() {
126 myPathMacros.removeAllMacros();
127 for (Pair<String, String> pair : myMacros) {
128 final String value = pair.getSecond();
129 if (value != null && value.trim().length() > 0) {
130 myPathMacros.setMacro(pair.getFirst(), value.replace(File.separatorChar, '/'));
135 public void reset() {
136 obtainData();
139 private boolean hasMacroWithName(String name) {
140 for (Pair<String, String> macro : myMacros) {
141 if (name.equals(macro.getFirst())) {
142 return true;
145 return false;
148 private int indexOfMacroWithName(String name) {
149 for (int i = 0; i < myMacros.size(); i++) {
150 final Pair<String, String> pair = myMacros.get(i);
151 if (name.equals(pair.getFirst())) {
152 return i;
155 return -1;
158 private void obtainData() {
159 obtainMacroPairs(myMacros);
160 myTableModel.fireTableDataChanged();
163 private void obtainMacroPairs(final List<Pair<String, String>> macros) {
164 macros.clear();
165 final Set<String> macroNames = myPathMacros.getUserMacroNames();
166 for (String name : macroNames) {
167 macros.add(Pair.create(name, myPathMacros.getValue(name).replace('/', File.separatorChar)));
170 if (myUndefinedMacroNames != null) {
171 for (String undefinedMacroName : myUndefinedMacroNames) {
172 macros.add(new Pair<String, String>(undefinedMacroName, ""));
175 Collections.sort(macros, MACRO_COMPARATOR);
178 public void editMacro() {
179 if (getSelectedRowCount() != 1) {
180 return;
182 final int selectedRow = getSelectedRow();
183 final Pair<String, String> pair = myMacros.get(selectedRow);
184 final String title = ApplicationBundle.message("title.edit.variable");
185 final String macroName = pair.getFirst();
186 final PathMacroEditor macroEditor = new PathMacroEditor(title, macroName, pair.getSecond(), new EditValidator());
187 macroEditor.show();
188 if (macroEditor.isOK()) {
189 myMacros.remove(selectedRow);
190 myMacros.add(Pair.create(macroEditor.getName(), macroEditor.getValue()));
191 Collections.sort(myMacros, MACRO_COMPARATOR);
192 myTableModel.fireTableDataChanged();
196 public boolean isModified() {
197 final ArrayList<Pair<String, String>> macros = new ArrayList<Pair<String, String>>();
198 obtainMacroPairs(macros);
199 return !macros.equals(myMacros);
202 private class MyTableModel extends AbstractTableModel{
203 public int getColumnCount() {
204 return 2;
207 public int getRowCount() {
208 return myMacros.size();
211 public Class getColumnClass(int columnIndex) {
212 return String.class;
215 public Object getValueAt(int rowIndex, int columnIndex) {
216 final Pair<String, String> pair = myMacros.get(rowIndex);
217 switch (columnIndex) {
218 case NAME_COLUMN: return pair.getFirst();
219 case VALUE_COLUMN: return pair.getSecond();
221 LOG.error("Wrong indices");
222 return null;
225 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
228 public String getColumnName(int columnIndex) {
229 switch (columnIndex) {
230 case NAME_COLUMN: return ApplicationBundle.message("column.name");
231 case VALUE_COLUMN: return ApplicationBundle.message("column.value");
233 return null;
236 public boolean isCellEditable(int rowIndex, int columnIndex) {
237 return false;
241 private class AddValidator implements PathMacroEditor.Validator {
242 private final String myTitle;
244 public AddValidator(String title) {
245 myTitle = title;
248 public boolean checkName(String name) {
249 if (name.length() == 0) return false;
250 return PathMacrosCollector.MACRO_PATTERN.matcher("$" + name + "$").matches();
253 public boolean isOK(String name, String value) {
254 if(name.length() == 0) return false;
255 if (hasMacroWithName(name)) {
256 Messages.showErrorDialog(PathMacroTable.this,
257 ApplicationBundle.message("error.variable.already.exists", name), myTitle);
258 return false;
260 return true;
264 private static class EditValidator implements PathMacroEditor.Validator {
265 public boolean checkName(String name) {
266 if (name.length() == 0) return false;
267 return PathMacrosCollector.MACRO_PATTERN.matcher("$" + name + "$").matches();
270 public boolean isOK(String name, String value) {
271 return checkName(name);