/*
* Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan
*
* 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.goide.configuration;
import com.goide.project.GoApplicationLibrariesService;
import com.goide.project.GoModuleLibrariesService;
import com.goide.project.GoProjectLibrariesService;
import com.goide.sdk.GoSdkUtil;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.HideableDecorator;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
public class GoLibrariesConfigurableProvider extends ConfigurableProvider {
@NotNull private final Project myProject;
public GoLibrariesConfigurableProvider(@NotNull Project project) {
myProject = project;
}
@Nullable
@Override
public Configurable createConfigurable() {
return createConfigurable(false);
}
@Nullable
private Configurable createConfigurable(boolean dialogMode) {
return new CompositeConfigurable<UnnamedConfigurable>() {
@Nullable
@Override
public JComponent createComponent() {
List<UnnamedConfigurable> configurables = getConfigurables();
Collection<HideableDecorator> hideableDecorators = ContainerUtil.newHashSet();
GridLayoutManager layoutManager = new GridLayoutManager(configurables.size() + 1, 1, new Insets(0, 0, 0, 0), -1, -1);
JPanel rootPanel = new JPanel(layoutManager);
Spacer spacer = new Spacer();
rootPanel.add(spacer, new GridConstraints(configurables.size(), 0, 1, 1, GridConstraints.ANCHOR_SOUTH,
GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
GridConstraints.SIZEPOLICY_FIXED, null, null, null));
for (int i = 0; i < configurables.size(); i++) {
UnnamedConfigurable configurable = configurables.get(i);
JComponent configurableComponent = configurable.createComponent();
assert configurableComponent != null;
JPanel hideablePanel = new JPanel(new BorderLayout());
rootPanel.add(hideablePanel, configurableConstrains(i));
if (configurable instanceof Configurable) {
String displayName = ((Configurable)configurable).getDisplayName();
ListenableHideableDecorator decorator = new ListenableHideableDecorator(hideablePanel, displayName, configurableComponent);
decorator.addListener(new MyHideableDecoratorListener(layoutManager, hideablePanel,
spacer, hideableDecorators,
configurableExpandedPropertyKey((Configurable)configurable)
));
hideableDecorators.add(decorator);
decorator.setOn(isConfigurableExpanded(i, (Configurable)configurable));
}
}
if (dialogMode) {
rootPanel.setPreferredSize(new Dimension(400, 600));
}
rootPanel.revalidate();
return rootPanel;
}
@NotNull
@Override
protected List<UnnamedConfigurable> createConfigurables() {
List<UnnamedConfigurable> result = ContainerUtil.newArrayList();
String[] urlsFromEnv = ContainerUtil.map2Array(GoSdkUtil.getGoPathsRootsFromEnvironment(), String.class, VirtualFile::getUrl);
result.add(new GoLibrariesConfigurable("Global libraries", GoApplicationLibrariesService.getInstance(), urlsFromEnv));
if (!myProject.isDefault()) {
result.add(new GoLibrariesConfigurable("Project libraries", GoProjectLibrariesService.getInstance(myProject)));
result.add(new GoModuleAwareConfigurable(myProject, "Module libraries", null) {
@NotNull
@Override
protected UnnamedConfigurable createModuleConfigurable(@NotNull Module module) {
return new GoLibrariesConfigurable("Module libraries", GoModuleLibrariesService.getInstance(module));
}
});
}
return result;
}
@NotNull
@Nls
@Override
public String getDisplayName() {
return "Go Libraries";
}
@Nullable
@Override
public String getHelpTopic() {
return null;
}
@NotNull
private GridConstraints configurableConstrains(int i) {
return new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_NORTHEAST, GridConstraints.FILL_BOTH,
GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_WANT_GROW |
GridConstraints.SIZEPOLICY_CAN_SHRINK,
GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_CAN_SHRINK,
null, null, null);
}
private boolean isConfigurableExpanded(int index, @NotNull Configurable configurable) {
return PropertiesComponent.getInstance(myProject).getBoolean(configurableExpandedPropertyKey(configurable), index < 2);
}
private void storeConfigurableExpandedProperty(@NotNull String storeKey, @NotNull Boolean value) {
PropertiesComponent.getInstance(myProject).setValue(storeKey, value.toString());
}
private String configurableExpandedPropertyKey(@NotNull Configurable configurable) {
String keyName = "configurable " + configurable.getDisplayName() + " is expanded".toLowerCase(Locale.US);
return StringUtil.replaceChar(keyName, ' ', '.');
}
class MyHideableDecoratorListener extends ListenableHideableDecorator.MyListener {
private final GridLayoutManager myLayoutManager;
private final JPanel myHideablePanel;
@NotNull private final String myStoreKey;
private final Spacer mySpacer;
private final Collection<HideableDecorator> myHideableDecorators;
public MyHideableDecoratorListener(@NotNull GridLayoutManager layoutManager,
@NotNull JPanel hideablePanel,
@NotNull Spacer spacer,
@NotNull Collection<HideableDecorator> hideableDecorators,
@NotNull String storeKey) {
myLayoutManager = layoutManager;
myHideablePanel = hideablePanel;
myStoreKey = storeKey;
mySpacer = spacer;
myHideableDecorators = hideableDecorators;
}
@Override
public void on() {
GridConstraints c = myLayoutManager.getConstraintsForComponent(myHideablePanel);
c.setVSizePolicy(c.getVSizePolicy() | GridConstraints.SIZEPOLICY_WANT_GROW);
GridConstraints spacerConstraints = myLayoutManager.getConstraintsForComponent(mySpacer);
spacerConstraints.setVSizePolicy(spacerConstraints.getVSizePolicy() & ~GridConstraints.SIZEPOLICY_WANT_GROW);
storeConfigurableExpandedProperty(myStoreKey, Boolean.TRUE);
}
@Override
public void beforeOff() {
GridConstraints c = myLayoutManager.getConstraintsForComponent(myHideablePanel);
c.setVSizePolicy(c.getVSizePolicy() & ~GridConstraints.SIZEPOLICY_WANT_GROW);
}
@Override
public void afterOff() {
if (isAllDecoratorsCollapsed()) {
GridConstraints c = myLayoutManager.getConstraintsForComponent(mySpacer);
c.setVSizePolicy(c.getVSizePolicy() | GridConstraints.SIZEPOLICY_WANT_GROW);
}
storeConfigurableExpandedProperty(myStoreKey, Boolean.FALSE);
}
private boolean isAllDecoratorsCollapsed() {
for (HideableDecorator hideableDecorator : myHideableDecorators) {
if (hideableDecorator.isExpanded()) {
return false;
}
}
return true;
}
}
};
}
public static void showModulesConfigurable(@NotNull Project project) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (!project.isDisposed()) {
Configurable configurable = new GoLibrariesConfigurableProvider(project).createConfigurable(true);
ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
}
}
}