/*
* 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 org.napile.idea.thermit.config.impl.configuration;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.napile.idea.thermit.ThermitBundle;
import org.napile.idea.thermit.config.impl.AntInstallation;
import org.napile.idea.thermit.config.impl.AntReference;
import org.napile.idea.thermit.config.impl.GlobalThermitConfiguration;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.config.AbstractProperty;
import com.intellij.util.config.StorageAccessors;
import com.intellij.util.containers.HashMap;
public class AntSetPanel
{
private final Form myForm;
private final GlobalThermitConfiguration myAntConfiguration;
public AntSetPanel()
{
this(GlobalThermitConfiguration.getInstance());
}
AntSetPanel(GlobalThermitConfiguration antConfiguration)
{
myAntConfiguration = antConfiguration;
myForm = new Form(antConfiguration);
}
@Nullable
public AntInstallation showDialog(JComponent parent)
{
final DialogWrapper dialog = new MyDialog(parent);
dialog.show();
if(!dialog.isOK())
{
return null;
}
apply();
return myForm.getSelectedAnt();
}
void reset()
{
myForm.setAnts(myAntConfiguration.getConfiguredAnts().values());
}
void apply()
{
for(AntInstallation ant : myForm.getRemovedAnts())
{
myAntConfiguration.removeConfiguration(ant);
}
final Map<AntReference, AntInstallation> currentAnts = myAntConfiguration.getConfiguredAnts();
for(AntInstallation installation : currentAnts.values())
{
installation.updateClasspath();
}
for(AntInstallation ant : myForm.getAddedAnts())
{
myAntConfiguration.addConfiguration(ant);
}
myForm.applyModifications();
}
public void setSelection(AntInstallation antInstallation)
{
myForm.selectAnt(antInstallation);
}
public JComponent getComponent()
{
return myForm.getComponent();
}
private static class Form implements AntUIUtil.PropertiesEditor<AntInstallation>
{
private final Splitter mySplitter = new Splitter(false);
private final StorageAccessors myAccessors = StorageAccessors.createGlobal("antConfigurations");
private final RightPanel myRightPanel;
private final AnActionListEditor<AntInstallation> myAnts = new AnActionListEditor<AntInstallation>();
private final UIPropertyBinding.Composite myBinding = new UIPropertyBinding.Composite();
private final EditPropertyContainer myGlobalWorkingProperties;
private final Map<AntInstallation, EditPropertyContainer> myWorkingProperties = new HashMap<AntInstallation, EditPropertyContainer>();
private AntInstallation myCurrent;
private final PropertyChangeListener myImmediateUpdater = new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent evt)
{
myBinding.apply(getProperties(myCurrent));
myAnts.updateItem(myCurrent);
}
};
public Form(final GlobalThermitConfiguration antInstallation)
{
mySplitter.setProportion(myAccessors.getFloat("splitter", 0.3f));
mySplitter.setShowDividerControls(true);
mySplitter.setFirstComponent(myAnts);
myGlobalWorkingProperties = new EditPropertyContainer(antInstallation.getProperties());
myRightPanel = new RightPanel(myBinding, myImmediateUpdater);
mySplitter.setSecondComponent(myRightPanel.myWholePanel);
myAnts.addAddAction(new NewAntFactory(myAnts));
myAnts.addRemoveButtonForAnt(antInstallation.IS_USER_ANT, ThermitBundle.message("remove.action.name"));
myAnts.actionsBuilt();
JList list = myAnts.getList();
list.setCellRenderer(new AntUIUtil.AntInstallationRenderer(this));
list.getSelectionModel().addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent e)
{
if(myCurrent != null)
myBinding.apply(getProperties(myCurrent));
myCurrent = myAnts.getSelectedItem();
if(myCurrent == null)
{
myBinding.loadValues(AbstractProperty.AbstractPropertyContainer.EMPTY);
myBinding.beDisabled();
}
else
{
if(antInstallation.IS_USER_ANT.value(myCurrent))
{
myBinding.beEnabled();
}
else
{
myBinding.beDisabled();
}
myBinding.loadValues(getProperties(myCurrent));
}
}
});
}
public JList getAntsList()
{
return myAnts.getList();
}
public JComponent getComponent()
{
return mySplitter;
}
public AntInstallation getSelectedAnt()
{
return myAnts.getSelectedItem();
}
public void setAnts(Collection<AntInstallation> antInstallations)
{
myAnts.setItems(antInstallations);
}
public void applyModifications()
{
if(myCurrent != null)
myBinding.apply(getProperties(myCurrent));
ArrayList<AbstractProperty> properties = new ArrayList<AbstractProperty>();
myBinding.addAllPropertiesTo(properties);
for(AntInstallation ant : myWorkingProperties.keySet())
{
EditPropertyContainer container = myWorkingProperties.get(ant);
container.apply();
}
myGlobalWorkingProperties.apply();
}
public void selectAnt(AntInstallation antInstallation)
{
myAnts.setSelection(antInstallation);
}
public ArrayList<AntInstallation> getAddedAnts()
{
return myAnts.getAdded();
}
public ArrayList<AntInstallation> getRemovedAnts()
{
return myAnts.getRemoved();
}
public EditPropertyContainer getProperties(AntInstallation ant)
{
EditPropertyContainer properties = myWorkingProperties.get(ant);
if(properties != null)
return properties;
properties = new EditPropertyContainer(myGlobalWorkingProperties, ant.getProperties());
myWorkingProperties.put(ant, properties);
return properties;
}
private static class RightPanel
{
private JLabel myNameLabel;
private JLabel myHome;
private JTextField myName;
private AntClasspathEditorPanel myClasspath;
private JPanel myWholePanel;
public RightPanel(UIPropertyBinding.Composite binding, PropertyChangeListener immediateUpdater)
{
myNameLabel.setLabelFor(myName);
binding.addBinding(myClasspath.setClasspathProperty(AntInstallation.CLASS_PATH));
binding.bindString(myHome, AntInstallation.HOME_DIR);
binding.bindString(myName, AntInstallation.NAME).addChangeListener(immediateUpdater);
}
}
}
private static class NewAntFactory implements Factory<AntInstallation>
{
private final AnActionListEditor<AntInstallation> myParent;
public NewAntFactory(AnActionListEditor<AntInstallation> parent)
{
myParent = parent;
}
public AntInstallation create()
{
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
VirtualFile file = FileChooser.chooseFile(descriptor, myParent, null, null);
if(file == null)
return null;
try
{
final AntInstallation inst = AntInstallation.fromHome(file.getPresentableUrl());
adjustName(inst);
return inst;
}
catch(AntInstallation.ConfigurationException e)
{
Messages.showErrorDialog(myParent, e.getMessage(), ThermitBundle.message("ant.setup.dialog.title"));
return null;
}
}
private void adjustName(final AntInstallation justCreated)
{
int nameIndex = 0;
String adjustedName = justCreated.getName();
final ListModel model = myParent.getList().getModel();
int idx = 0;
while(idx < model.getSize())
{
final AntInstallation inst = (AntInstallation) model.getElementAt(idx++);
if(adjustedName.equals(inst.getName()))
{
adjustedName = justCreated.getName() + " (" + (++nameIndex) + ")";
idx = 0; // search from beginning
}
}
if(!adjustedName.equals(justCreated.getName()))
{
justCreated.setName(adjustedName);
}
}
}
private class MyDialog extends DialogWrapper
{
public MyDialog(final JComponent parent)
{
super(parent, true);
setTitle(ThermitBundle.message("configure.ant.dialog.title"));
init();
}
@Nullable
protected JComponent createCenterPanel()
{
return myForm.getComponent();
}
@NonNls
protected String getDimensionServiceKey()
{
return "antSetDialogDimensionKey";
}
public JComponent getPreferredFocusedComponent()
{
return myForm.getAntsList();
}
protected void doOKAction()
{
final Set<String> names = new HashSet<String>();
final ListModel model = myForm.getAntsList().getModel();
for(int idx = 0; idx < model.getSize(); idx++)
{
final AntInstallation inst = (AntInstallation) model.getElementAt(idx);
final String name = AntInstallation.NAME.get(myForm.getProperties(inst));
if(names.contains(name))
{
Messages.showErrorDialog("Duplicate thermit installation name: \"" + name + "\"", getTitle());
return;
}
names.add(name);
}
super.doOKAction();
}
}
}