/* * Copyright 2000-2014 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.openapi.options.ex; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.options.*; import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; 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.util.List; /** * @author Dmitry Avdeev * Date: 9/17/12 */ public class ConfigurableWrapper implements SearchableConfigurable { private static final ConfigurableWrapper[] EMPTY_ARRAY = new ConfigurableWrapper[0]; private static final NullableFunction,Configurable> CONFIGURABLE_FUNCTION = new NullableFunction, Configurable>() { @Override public Configurable fun(ConfigurableEP ep) { return wrapConfigurable(ep); } }; private static final Logger LOG = Logger.getInstance(ConfigurableWrapper.class); @Nullable public static T wrapConfigurable(ConfigurableEP ep) { if (!ep.canCreateConfigurable()) { return null; } if (ep.displayName != null || ep.key != null || ep.groupId != null) { T configurable = null; if (ep.providerClass != null) { configurable = ep.createConfigurable(); if (configurable == null) { return null; // it is allowed to return null from provider } } return !ep.dynamic && ep.children == null && ep.childrenEPName == null ? (T)new ConfigurableWrapper(ep, configurable) : (T)new CompositeWrapper(ep, configurable); } else { return ep.createConfigurable(); } } public static List createConfigurables(ExtensionPointName> name) { return ContainerUtil.mapNotNull(name.getExtensions(), new NullableFunction, T>() { @Override public T fun(ConfigurableEP ep) { return wrapConfigurable(ep); } }); } public static boolean isNoScroll(Configurable configurable) { return configurable instanceof NoScroll || (configurable instanceof ConfigurableWrapper && ((ConfigurableWrapper)configurable).getConfigurable() instanceof NoScroll); } public static boolean isNonDefaultProject(Configurable configurable) { return configurable instanceof NonDefaultProjectConfigurable || (configurable instanceof ConfigurableWrapper && ((ConfigurableWrapper)configurable).myEp.nonDefaultProject); } private final ConfigurableEP myEp; private ConfigurableWrapper(@NotNull ConfigurableEP ep, @Nullable UnnamedConfigurable configurable) { myEp = ep; myConfigurable = configurable; } private UnnamedConfigurable myConfigurable; public UnnamedConfigurable getConfigurable() { if (myConfigurable == null) { myConfigurable = myEp.createConfigurable(); if (myConfigurable == null) { LOG.error("Can't instantiate configurable for " + myEp); } } return myConfigurable; } @Nls @Override public String getDisplayName() { if (myEp.displayName == null && myEp.key == null) { UnnamedConfigurable configurable = getConfigurable(); if (configurable instanceof Configurable) { return ((Configurable)configurable).getDisplayName(); } } return myEp.getDisplayName(); } public String getInstanceClass() { return myEp.instanceClass; } public String getProviderClass() { return myEp.providerClass; } @Nullable @Override public String getHelpTopic() { UnnamedConfigurable configurable = getConfigurable(); return configurable instanceof Configurable ? ((Configurable)configurable).getHelpTopic() : null; } @Nullable @Override public JComponent createComponent() { return getConfigurable().createComponent(); } @Override public boolean isModified() { return getConfigurable().isModified(); } @Override public void apply() throws ConfigurationException { getConfigurable().apply(); } @Override public void reset() { getConfigurable().reset(); } @Override public void disposeUIResources() { getConfigurable().disposeUIResources(); } @NotNull @Override public String getId() { if (myEp.id != null) { return myEp.id; } UnnamedConfigurable configurable = getConfigurable(); if (configurable instanceof SearchableConfigurable) { return ((SearchableConfigurable)configurable).getId(); } return myEp.instanceClass != null ? myEp.instanceClass : myEp.providerClass; } @NotNull public ConfigurableEP getExtensionPoint() { return myEp; } public String getParentId() { return myEp.parentId; } public ConfigurableWrapper addChild(Configurable configurable) { return new CompositeWrapper(myEp, null, configurable); } @Override public String toString() { return getDisplayName(); } @Nullable @Override public Runnable enableSearch(String option) { final UnnamedConfigurable configurable = getConfigurable(); return configurable instanceof SearchableConfigurable ? ((SearchableConfigurable)configurable).enableSearch(option) : null; } private static class CompositeWrapper extends ConfigurableWrapper implements Configurable.Composite { private Configurable[] myKids; private CompositeWrapper(@NotNull ConfigurableEP ep, @Nullable UnnamedConfigurable configurable, Configurable... kids) { super(ep, configurable); if (ep.dynamic) { kids = ((Composite)getConfigurable()).getConfigurables(); } else if (ep.children != null) { kids = ContainerUtil.mapNotNull(ep.getChildren(), new NullableFunction() { @Override public ConfigurableWrapper fun(ConfigurableEP ep) { return ep.isAvailable() ? (ConfigurableWrapper)wrapConfigurable(ep) : null; } }, EMPTY_ARRAY); } if (ep.childrenEPName != null) { ExtensionPoint childrenEP = Extensions.getArea(ep.getProject()).getExtensionPoint(ep.childrenEPName); Object[] extensions = childrenEP.getExtensions(); if (extensions.length > 0) { if (extensions[0] instanceof ConfigurableEP) { Configurable[] children = ContainerUtil.mapNotNull(((ConfigurableEP[])extensions), CONFIGURABLE_FUNCTION, new Configurable[0]); kids = ArrayUtil.mergeArrays(kids, children); } else { kids = ArrayUtil.mergeArrays(kids, ((Composite)getConfigurable()).getConfigurables()); } } } myKids = kids; } @Override public Configurable[] getConfigurables() { return myKids; } @Override public ConfigurableWrapper addChild(Configurable configurable) { myKids = ArrayUtil.append(myKids, configurable); return this; } } }