| /* |
| * 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.xdebugger.impl.settings; |
| |
| import com.intellij.openapi.options.Configurable; |
| import com.intellij.openapi.options.ConfigurationException; |
| import com.intellij.openapi.options.SearchableConfigurable; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.util.SmartList; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.xdebugger.XDebuggerBundle; |
| import com.intellij.xdebugger.breakpoints.XBreakpointType; |
| import com.intellij.xdebugger.impl.DebuggerSupport; |
| import com.intellij.xdebugger.settings.DebuggerConfigurableProvider; |
| import com.intellij.xdebugger.settings.DebuggerSettingsCategory; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.util.*; |
| |
| public class DebuggerConfigurable implements SearchableConfigurable.Parent { |
| public static final String DISPLAY_NAME = XDebuggerBundle.message("debugger.configurable.display.name"); |
| |
| static final Configurable[] EMPTY_CONFIGURABLES = new Configurable[0]; |
| private static final DebuggerSettingsCategory[] MERGED_CATEGORIES = {DebuggerSettingsCategory.STEPPING, DebuggerSettingsCategory.HOTSWAP}; |
| |
| private Configurable myRootConfigurable; |
| private Configurable[] myChildren; |
| |
| @Override |
| public String getDisplayName() { |
| return DISPLAY_NAME; |
| } |
| |
| @Override |
| public String getHelpTopic() { |
| return myRootConfigurable != null ? myRootConfigurable.getHelpTopic() : null; |
| } |
| |
| @Override |
| public Configurable[] getConfigurables() { |
| compute(); |
| |
| if (myChildren.length == 0 && myRootConfigurable instanceof SearchableConfigurable.Parent) { |
| return ((Parent)myRootConfigurable).getConfigurables(); |
| } |
| else { |
| return myChildren; |
| } |
| } |
| |
| private void compute() { |
| if (myChildren != null) { |
| return; |
| } |
| |
| List<Configurable> configurables = new SmartList<Configurable>(); |
| configurables.add(new DataViewsConfigurable()); |
| |
| DebuggerConfigurableProvider[] providers = DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions(); |
| computeMergedConfigurables(providers, configurables); |
| |
| //noinspection deprecation |
| for (DebuggerSettingsPanelProvider provider : getSortedProviders()) { |
| configurables.addAll(provider.getConfigurables()); |
| @SuppressWarnings("deprecation") |
| Configurable providerRootConfigurable = provider.getRootConfigurable(); |
| if (providerRootConfigurable != null) { |
| configurables.add(providerRootConfigurable); |
| } |
| } |
| |
| for (DebuggerConfigurableProvider provider : providers) { |
| configurables.addAll(provider.getConfigurables(DebuggerSettingsCategory.ROOT)); |
| } |
| |
| MergedCompositeConfigurable mergedGeneralConfigurable = computeGeneralConfigurables(providers); |
| if (configurables.isEmpty() && mergedGeneralConfigurable == null) { |
| myRootConfigurable = null; |
| myChildren = EMPTY_CONFIGURABLES; |
| } |
| else if (configurables.size() == 1) { |
| Configurable firstConfigurable = configurables.get(0); |
| if (mergedGeneralConfigurable == null) { |
| myRootConfigurable = firstConfigurable; |
| myChildren = EMPTY_CONFIGURABLES; |
| } |
| else { |
| Configurable[] generalConfigurables = mergedGeneralConfigurable.children; |
| Configurable[] mergedArray = new Configurable[generalConfigurables.length + 1]; |
| System.arraycopy(generalConfigurables, 0, mergedArray, 0, generalConfigurables.length); |
| mergedArray[generalConfigurables.length] = firstConfigurable; |
| myRootConfigurable = new MergedCompositeConfigurable("", "", mergedArray); |
| myChildren = firstConfigurable instanceof SearchableConfigurable.Parent ? ((Parent)firstConfigurable).getConfigurables() : EMPTY_CONFIGURABLES; |
| } |
| } |
| else { |
| myChildren = configurables.toArray(new Configurable[configurables.size()]); |
| myRootConfigurable = mergedGeneralConfigurable; |
| } |
| } |
| |
| private static void computeMergedConfigurables(@NotNull DebuggerConfigurableProvider[] providers, @NotNull List<Configurable> result) { |
| for (DebuggerSettingsCategory category : MERGED_CATEGORIES) { |
| List<Configurable> configurables = getConfigurables(category, providers); |
| if (!configurables.isEmpty()) { |
| String id = category.name().toLowerCase(Locale.ENGLISH); |
| result.add(new MergedCompositeConfigurable("debugger." + id, XDebuggerBundle.message("debugger." + id + ".display.name"), |
| configurables.toArray(new Configurable[configurables.size()]))); |
| } |
| } |
| } |
| |
| @Nullable |
| private static MergedCompositeConfigurable computeGeneralConfigurables(@NotNull DebuggerConfigurableProvider[] providers) { |
| List<Configurable> rootConfigurables = getConfigurables(DebuggerSettingsCategory.GENERAL, providers); |
| if (rootConfigurables.isEmpty()) { |
| return null; |
| } |
| |
| Configurable[] mergedRootConfigurables = rootConfigurables.toArray(new Configurable[rootConfigurables.size()]); |
| // move unnamed to top |
| Arrays.sort(mergedRootConfigurables, new Comparator<Configurable>() { |
| @Override |
| public int compare(@NotNull Configurable o1, @NotNull Configurable o2) { |
| boolean c1e = StringUtil.isEmpty(o1.getDisplayName()); |
| return c1e == StringUtil.isEmpty(o2.getDisplayName()) ? 0 : (c1e ? -1 : 1); |
| } |
| }); |
| return new MergedCompositeConfigurable("", "", mergedRootConfigurables); |
| } |
| |
| @Override |
| public void apply() throws ConfigurationException { |
| if (myRootConfigurable != null) { |
| myRootConfigurable.apply(); |
| } |
| } |
| |
| @Override |
| public boolean hasOwnContent() { |
| compute(); |
| return myRootConfigurable != null; |
| } |
| |
| @Override |
| public boolean isVisible() { |
| return XBreakpointType.EXTENSION_POINT_NAME.getExtensions().length != 0; |
| } |
| |
| @Override |
| public Runnable enableSearch(final String option) { |
| return null; |
| } |
| |
| @Override |
| public JComponent createComponent() { |
| compute(); |
| return myRootConfigurable != null ? myRootConfigurable.createComponent() : null; |
| } |
| |
| @Override |
| public boolean isModified() { |
| return myRootConfigurable != null && myRootConfigurable.isModified(); |
| } |
| |
| @Override |
| public void reset() { |
| if (myRootConfigurable != null) { |
| myRootConfigurable.reset(); |
| } |
| } |
| |
| @Override |
| public void disposeUIResources() { |
| if (myRootConfigurable != null) { |
| myRootConfigurable.disposeUIResources(); |
| } |
| } |
| |
| @Override |
| @NotNull |
| @NonNls |
| public String getId() { |
| return "project.propDebugger"; |
| } |
| |
| @SuppressWarnings("deprecation") |
| @NotNull |
| private static List<DebuggerSettingsPanelProvider> getSortedProviders() { |
| List<DebuggerSettingsPanelProvider> providers = null; |
| for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) { |
| DebuggerSettingsPanelProvider provider = support.getSettingsPanelProvider(); |
| if (providers == null) { |
| providers = new SmartList<DebuggerSettingsPanelProvider>(); |
| } |
| providers.add(provider); |
| } |
| |
| if (ContainerUtil.isEmpty(providers)) { |
| return Collections.emptyList(); |
| } |
| |
| if (providers.size() > 1) { |
| Collections.sort(providers, new Comparator<DebuggerSettingsPanelProvider>() { |
| @Override |
| public int compare(@NotNull DebuggerSettingsPanelProvider o1, @NotNull DebuggerSettingsPanelProvider o2) { |
| return o2.getPriority() - o1.getPriority(); |
| } |
| }); |
| } |
| return providers; |
| } |
| |
| @NotNull |
| static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) { |
| return getConfigurables(category, DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions()); |
| } |
| |
| @NotNull |
| private static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category, @NotNull DebuggerConfigurableProvider[] providers) { |
| List<Configurable> configurables = null; |
| for (DebuggerConfigurableProvider provider : providers) { |
| Collection<? extends Configurable> providerConfigurables = provider.getConfigurables(category); |
| if (!providerConfigurables.isEmpty()) { |
| if (configurables == null) { |
| configurables = new SmartList<Configurable>(); |
| } |
| configurables.addAll(providerConfigurables); |
| } |
| } |
| return ContainerUtil.notNullize(configurables); |
| } |
| } |