/*
* Copyright 2010 Ronnie Kolehmainen
*
* 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.github.cssxfire;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.NonDefaultProjectConfigurable;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.util.ui.tree.AbstractFileTreeTable;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.ScrollPaneUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: Ronnie
*/
public class ProjectSettingsConfigurable implements SearchableConfigurable, NonDefaultProjectConfigurable {
public static ProjectSettingsConfigurable getInstance(final Project project) {
return new ProjectSettingsConfigurable(project);
}
private Project myProject;
private JCheckBox checkBoxAutoClear;
private JCheckBox checkBoxMediaReduce;
private JCheckBox checkBoxFileReduce;
private JCheckBox checkBoxUseRoutes;
private JCheckBox checkBoxCurrentDocumentsReduce;
private JCheckBox checkBoxResolveVariables;
private JCheckBox checkBoxResolveMixins;
private FileTreeTable routesTable;
private JScrollPane routesScrollPane;
private JPanel myPanel;
private JButton buttonSetRoot;
public ProjectSettingsConfigurable(Project project) {
myProject = project;
}
public String getId() {
return getClass().getName();
}
public Runnable enableSearch(String option) {
return null;
}
public JComponent createComponent() {
routesTable = new FileTreeTable();
routesTable.getColumnModel().getColumn(0).setPreferredWidth(260);
routesTable.getColumnModel().getColumn(1).setPreferredWidth(240);
routesScrollPane.setViewportView(routesTable);
routesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
updateWebRootButton();
}
});
buttonSetRoot.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
updateWebRoot();
}
});
reset();
updateWebRootButton();
return myPanel;
}
private void updateWebRoot() {
int selectedRow = routesTable.getSelectedRow();
if (selectedRow != -1) {
Map<VirtualFile, String> currentValues = routesTable.getValues();
Object file = routesTable.getValueAt(selectedRow, 0);
if (file instanceof VirtualFile) {
for (VirtualFile key : new HashSet<VirtualFile>(currentValues.keySet())) {
if ("/".equals(currentValues.get(key))) {
currentValues.remove(key);
}
}
currentValues.put((VirtualFile) file, "/");
}
routesTable.reset(currentValues);
updateWebRootButton();
}
}
private void updateWebRootButton() {
int selectedRow = routesTable.getSelectedRow();
if (selectedRow == -1) {
buttonSetRoot.setEnabled(false);
return;
}
Object file = routesTable.getValueAt(selectedRow, 0);
Object route = routesTable.getValueAt(selectedRow, 1);
buttonSetRoot.setEnabled(!"/".equals(route) && file instanceof VirtualFile && ((VirtualFile) file).isDirectory());
}
public boolean isModified() {
ProjectSettings state = ProjectSettings.getInstance(myProject);
return !state.getRoutes().getMappings().equals(routesTable.getValues())
|| state.isAutoClear() != checkBoxAutoClear.isSelected()
|| state.isMediaReduce() != checkBoxMediaReduce.isSelected()
|| state.isFileReduce() != checkBoxFileReduce.isSelected()
|| state.isUseRoutes() != checkBoxUseRoutes.isSelected()
|| state.isCurrentDocumentsReduce() != checkBoxCurrentDocumentsReduce.isSelected()
|| state.isResolveVariables() != checkBoxResolveVariables.isSelected()
|| state.isResolveMixins() != checkBoxResolveMixins.isSelected();
}
public void apply() throws ConfigurationException {
ProjectSettings state = ProjectSettings.getInstance(myProject);
state.getRoutes().setMappings(routesTable.getValues());
state.setAutoClear(checkBoxAutoClear.isSelected());
state.setMediaReduce(checkBoxMediaReduce.isSelected());
state.setFileReduce(checkBoxFileReduce.isSelected());
state.setCurrentDocumentsReduce(checkBoxCurrentDocumentsReduce.isSelected());
state.setResolveVariables(checkBoxResolveVariables.isSelected());
state.setResolveMixins(checkBoxResolveMixins.isSelected());
state.setUseRoutes(checkBoxUseRoutes.isSelected());
// set default values for new projects (legacy)
//noinspection ConstantConditions
CssXFireConnector.getInstance().getState().setMediaReduce(checkBoxMediaReduce.isSelected());
//noinspection ConstantConditions
CssXFireConnector.getInstance().getState().setSmartReduce(checkBoxFileReduce.isSelected());
}
public void reset() {
ProjectSettings state = ProjectSettings.getInstance(myProject);
routesTable.reset(state.getRoutes().getMappings());
checkBoxAutoClear.setSelected(state.isAutoClear());
checkBoxFileReduce.setSelected(state.isFileReduce());
checkBoxMediaReduce.setSelected(state.isMediaReduce());
checkBoxCurrentDocumentsReduce.setSelected(state.isCurrentDocumentsReduce());
checkBoxResolveVariables.setSelected(state.isResolveVariables());
checkBoxResolveMixins.setSelected(state.isResolveMixins());
checkBoxUseRoutes.setSelected(state.isUseRoutes());
}
public void disposeUIResources() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Nls
public String getDisplayName() {
return "CSS-X-Fire";
}
public Icon getIcon() {
return null;
}
public String getHelpTopic() {
return null;
}
private void createUIComponents() {
routesScrollPane = new MyScrollPane(new JTable());
}
private class FileTreeTable extends AbstractFileTreeTable<String> {
private FileTreeTable() {
super(myProject, String.class, "Route", VirtualFileFilter.ALL, false);
}
@Override
protected boolean isValueEditableForFile(VirtualFile virtualFile) {
if (virtualFile == null) {
return false;
}
return !virtualFile.getUrl().startsWith(getSettingsUrl());
}
@Override
protected boolean isNullObject(String value) {
/*
Disallow any route that has leading or trailing whitespace, or
does not start with a forward slash.
*/
if (value == null) {
return true;
}
String trimmed = value.trim();
return !trimmed.equals(value) || !trimmed.startsWith("/");
}
@NotNull
private String getSettingsUrl() {
VirtualFile settingsDir = myProject.getBaseDir();
return (settingsDir != null ? settingsDir.getUrl() : "") + "/.idea";
}
}
private static class MyScrollPane extends JScrollPane {
MyScrollPane(JComponent view) {
super(view);
}
/**
* Scrollpane's background should be always in sync with view's background
*/
public void setUI(ScrollPaneUI ui) {
super.setUI(ui);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Component component = getViewport().getView();
if (component != null) {
getViewport().setBackground(component.getBackground());
}
}
});
}
}
}