blob: 4c66ad7c47b57fd6b08382dd6f8fac71bd7fe16e [file] [log] [blame]
/*
* Copyright 2000-2009 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.uiDesigner.clientProperties;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.uiDesigner.UIDesignerBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.util.*;
/**
* @author yole
*/
public class ConfigureClientPropertiesDialog extends DialogWrapper {
private JTree myClassTree;
private JTable myPropertiesTable;
private Class mySelectedClass;
private ClientPropertiesManager.ClientProperty[] mySelectedProperties = new ClientPropertiesManager.ClientProperty[0];
private final MyTableModel myTableModel = new MyTableModel();
private final Project myProject;
private final ClientPropertiesManager myManager;
private Splitter mySplitter;
final private PropertiesComponent myPropertiesComponent = PropertiesComponent.getInstance();
final private static String SPLITTER_PROPORTION_PROPERTY = "ConfigureClientPropertiesDialog.splitterProportion";
public ConfigureClientPropertiesDialog(final Project project) {
super(project, true);
myProject = project;
setTitle(UIDesignerBundle.message("client.properties.title"));
myManager = ClientPropertiesManager.getInstance(project).clone();
init();
}
public void save() {
ClientPropertiesManager.getInstance(myProject).saveFrom(myManager);
}
@Override
public void dispose() {
myPropertiesComponent.setValue(SPLITTER_PROPORTION_PROPERTY, String.valueOf(mySplitter.getProportion()));
super.dispose();
}
private void updateSelectedProperties() {
mySelectedProperties = myManager.getConfiguredProperties(mySelectedClass);
myTableModel.fireTableDataChanged();
}
@Nullable
protected JComponent createCenterPanel() {
myClassTree = new Tree();
myClassTree.setRootVisible(false);
myClassTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
final TreePath leadSelectionPath = e.getNewLeadSelectionPath();
if (leadSelectionPath == null) return;
final DefaultMutableTreeNode node = (DefaultMutableTreeNode)leadSelectionPath.getLastPathComponent();
mySelectedClass = (Class)node.getUserObject();
updateSelectedProperties();
}
});
myClassTree.setCellRenderer(new ColoredTreeCellRenderer() {
public void customizeCellRenderer(JTree tree,
Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
if (node.getUserObject() instanceof Class) {
Class cls = (Class)node.getUserObject();
if (cls != null) {
append(cls.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
}
});
fillClassTree();
myPropertiesTable = new JBTable();
myPropertiesTable.setModel(myTableModel);
mySplitter = new Splitter(false, Float.valueOf(myPropertiesComponent.getValue(SPLITTER_PROPORTION_PROPERTY, "0.5f")));
mySplitter.setFirstComponent(
ToolbarDecorator.createDecorator(myClassTree)
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
ClassNameInputDialog dlg = new ClassNameInputDialog(myProject, mySplitter);
dlg.show();
if (dlg.getExitCode() == OK_EXIT_CODE) {
String className = dlg.getClassName();
if (className.length() == 0) return;
final Class aClass;
try {
aClass = Class.forName(className);
}
catch (ClassNotFoundException ex) {
Messages.showErrorDialog(mySplitter,
UIDesignerBundle.message("client.properties.class.not.found", className),
UIDesignerBundle.message("client.properties.title"));
return;
}
if (!JComponent.class.isAssignableFrom(aClass)) {
Messages.showErrorDialog(mySplitter,
UIDesignerBundle
.message("client.properties.class.not.component", className),
UIDesignerBundle.message("client.properties.title"));
return;
}
myManager.addClientPropertyClass(className);
fillClassTree();
}
}
}).setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
if (mySelectedClass != null) {
myManager.removeClientPropertyClass(mySelectedClass);
fillClassTree();
}
}
}).setToolbarPosition(SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT).createPanel());
mySplitter.setSecondComponent(
ToolbarDecorator.createDecorator(myPropertiesTable).disableUpDownActions()
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
AddClientPropertyDialog dlg = new AddClientPropertyDialog(myProject);
dlg.show();
if (dlg.getExitCode() == OK_EXIT_CODE) {
ClientPropertiesManager.ClientProperty[] props = myManager.getClientProperties(mySelectedClass);
for (ClientPropertiesManager.ClientProperty prop : props) {
if (prop.getName().equalsIgnoreCase(dlg.getEnteredProperty().getName())) {
Messages.showErrorDialog(mySplitter,
UIDesignerBundle.message("client.properties.already.defined", prop.getName()),
UIDesignerBundle.message("client.properties.title"));
return;
}
}
myManager.addConfiguredProperty(mySelectedClass, dlg.getEnteredProperty());
updateSelectedProperties();
}
}
}).setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
int row = myPropertiesTable.getSelectedRow();
if (row >= 0 && row < mySelectedProperties.length) {
myManager.removeConfiguredProperty(mySelectedClass, mySelectedProperties[row].getName());
updateSelectedProperties();
if (mySelectedProperties.length > 0) {
if (row >= mySelectedProperties.length) row--;
myPropertiesTable.getSelectionModel().setSelectionInterval(row, row);
}
}
}
}).createPanel());
return mySplitter;
}
private void fillClassTree() {
List<Class> configuredClasses = myManager.getConfiguredClasses();
Collections.sort(configuredClasses, new Comparator<Class>() {
public int compare(final Class o1, final Class o2) {
return getInheritanceLevel(o1) - getInheritanceLevel(o2);
}
private int getInheritanceLevel(Class aClass) {
int level = 0;
while (aClass.getSuperclass() != null) {
level++;
aClass = aClass.getSuperclass();
}
return level;
}
});
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
DefaultTreeModel treeModel = new DefaultTreeModel(root);
Map<Class, DefaultMutableTreeNode> classToNodeMap = new HashMap<Class, DefaultMutableTreeNode>();
for (Class cls : configuredClasses) {
DefaultMutableTreeNode parentNode = root;
Class superClass = cls.getSuperclass();
while (superClass != null) {
if (classToNodeMap.containsKey(superClass)) {
parentNode = classToNodeMap.get(superClass);
break;
}
superClass = superClass.getSuperclass();
}
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(cls);
classToNodeMap.put(cls, childNode);
parentNode.add(childNode);
}
myClassTree.setModel(treeModel);
myClassTree.expandRow(0);
myClassTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
myClassTree.getSelectionModel().setSelectionPath(new TreePath(new Object[]{root, root.getFirstChild()}));
}
@Override
@NonNls
protected String getDimensionServiceKey() {
return "ConfigureClientPropertiesDialog";
}
private class MyTableModel extends AbstractTableModel {
public int getRowCount() {
return mySelectedProperties.length;
}
public int getColumnCount() {
return 2;
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return mySelectedProperties[rowIndex].getName();
default:
return mySelectedProperties[rowIndex].getValueClass();
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return UIDesignerBundle.message("client.properties.name");
default:
return UIDesignerBundle.message("client.properties.class");
}
}
}
}