generic debugger settings: step 2 — stepping

This commit is contained in:
Vladimir Krivosheev
2014-07-21 19:08:38 +02:00
parent ff16ce78a1
commit 124d7744d4
11 changed files with 284 additions and 124 deletions
@@ -18,6 +18,7 @@ package com.intellij.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.ui.JavaDebuggerSupport;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.ui.classFilter.ClassFilterEditor;
@@ -75,7 +76,7 @@ public class DebuggerSteppingConfigurable implements SearchableConfigurable, Con
}
public String getDisplayName() {
return DebuggerBundle.message("debugger.stepping.configurable.display.name");
return OptionsBundle.message("options.java.display.name");
}
@NotNull
@@ -350,7 +350,6 @@ public class JavaDebuggerSupport extends DebuggerSupport {
@Override
public Collection<? extends Configurable> getConfigurables() {
final ArrayList<Configurable> configurables = new ArrayList<Configurable>();
configurables.add(new DebuggerSteppingConfigurable());
configurables.add(new UserRenderersConfigurable(null));
configurables.add(new DebuggerHotswapConfigurable());
return configurables;
@@ -367,16 +366,16 @@ public class JavaDebuggerSupport extends DebuggerSupport {
switch (category) {
case DATA_VIEWS:
return Collections.singletonList(new DebuggerDataViewsConfigurable(null));
case STEPPING:
return Collections.singletonList(new DebuggerSteppingConfigurable());
}
return Collections.emptyList();
}
@Override
public void applied(@NotNull XDebuggerSettings.Category category) {
switch (category) {
case DATA_VIEWS:
NodeRendererSettings.getInstance().fireRenderersChanged();
break;
if (category == XDebuggerSettings.Category.DATA_VIEWS) {
NodeRendererSettings.getInstance().fireRenderersChanged();
}
}
}
@@ -2,6 +2,7 @@ xdebugger.colors.page.name=Debugger
debugger.configurable.display.name=Debugger
debugger.dataViews.display.name=Data Views
debugger.stepping.display.name=Stepping
xdebugger.default.content.title=Debug
xdebugger.debugger.tab.title=Debugger
@@ -48,6 +48,10 @@ public class VerticalFlowLayout extends FlowLayout implements Serializable {
this(alignment, 5, 5, fillHorizontally, fillVertically);
}
public VerticalFlowLayout(int hGap, int vGap) {
this(TOP, hGap, vGap, true, false);
}
public VerticalFlowLayout(@VerticalFlowAlignment int alignment, int hGap, int vGap, boolean fillHorizontally, boolean fillVertically) {
setAlignment(alignment);
this.hGap = hGap;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -35,7 +35,17 @@ import org.jetbrains.annotations.Nullable;
*/
public abstract class XDebuggerSettings<T> implements PersistentStateComponent<T> {
public enum Category {
DATA_VIEWS
DATA_VIEWS(true), STEPPING(true);
private final boolean separatePage;
Category(boolean separatePage) {
this.separatePage = separatePage;
}
public boolean isSeparatePage() {
return separatePage;
}
}
public static final ExtensionPointName<XDebuggerSettings> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.settings");
@@ -16,138 +16,38 @@
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.ui.IdeBorderFactory;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.impl.DebuggerSupport;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.List;
class DataViewsConfigurable implements SearchableConfigurable.Parent {
private DataViewsConfigurableUi root;
private Configurable[] children;
private JComponent component;
@Override
public boolean hasOwnContent() {
return true;
}
@Override
public boolean isVisible() {
return true;
}
@Override
public Configurable[] getConfigurables() {
if (children == null) {
List<Configurable> configurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.DATA_VIEWS);
children = configurables.toArray(new Configurable[configurables.size()]);
}
return children.length == 1 ? DebuggerConfigurable.EMPTY_CONFIGURABLES : children;
}
class DataViewsConfigurable extends SubCompositeConfigurable implements Configurable.NoScroll {
@NotNull
@Override
public String getId() {
return "debugger.dataViews";
}
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
@Nls
@Override
public String getDisplayName() {
return XDebuggerBundle.message("debugger.dataViews.display.name");
}
@Nullable
@Override
public String getHelpTopic() {
getConfigurables();
return children.length == 1 ? children[0].getHelpTopic() : null;
protected DataViewsConfigurableUi createRootUi() {
return new DataViewsConfigurableUi();
}
@Nullable
@NotNull
@Override
public JComponent createComponent() {
if (component == null) {
if (root == null) {
root = new DataViewsConfigurableUi();
}
getConfigurables();
if (children.length == 1) {
JPanel panel = new JPanel(new BorderLayout(0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET));
panel.add(root.getComponent(), BorderLayout.NORTH);
Configurable configurable = children[0];
JComponent configurableComponent = configurable.createComponent();
assert configurableComponent != null;
configurableComponent.setBorder(IdeBorderFactory.createTitledBorder(configurable.getDisplayName(), false));
panel.add(configurableComponent, BorderLayout.CENTER);
component = panel;
}
else {
component = root.getComponent();
}
}
return component;
protected XDebuggerSettings.Category getCategory() {
return XDebuggerSettings.Category.DATA_VIEWS;
}
@NotNull
@Override
public boolean isModified() {
if (root != null && root.isModified(XDebuggerSettingsManager.getInstanceImpl().getDataViewSettings())) {
return true;
}
else {
return children.length == 1 && children[0].isModified();
}
}
@Override
public void apply() throws ConfigurationException {
if (root != null) {
root.apply(XDebuggerSettingsManager.getInstanceImpl().getDataViewSettings());
for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
support.getSettingsPanelProvider().applied(XDebuggerSettings.Category.DATA_VIEWS);
}
}
if (children.length == 1) {
children[0].apply();
}
}
@Override
public void reset() {
if (root != null) {
root.reset(XDebuggerSettingsManager.getInstanceImpl().getDataViewSettings());
}
if (children.length == 1) {
children[0].reset();
}
}
@Override
public void disposeUIResources() {
root = null;
component = null;
if (children.length == 1) {
children[0].disposeUIResources();
}
children = null;
protected XDebuggerDataViewSettings getSettings() {
return XDebuggerSettingsManager.getInstanceImpl().getDataViewSettings();
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.impl.DebuggerSupport;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -70,6 +71,11 @@ public class DebuggerConfigurable implements SearchableConfigurable.Parent {
List<Configurable> configurables = new ArrayList<Configurable>();
configurables.add(new DataViewsConfigurable());
List<Configurable> steppingConfigurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.STEPPING, providers);
if (!steppingConfigurables.isEmpty()) {
configurables.add(new SteppingConfigurable(steppingConfigurables));
}
Configurable rootConfigurable = null;
for (DebuggerSettingsPanelProvider provider : providers) {
configurables.addAll(provider.getConfigurables());
@@ -23,6 +23,7 @@ import com.intellij.xdebugger.impl.DebuggerSupport;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -65,14 +66,21 @@ public class DebuggerConfigurableProvider extends ConfigurableProvider {
@NotNull
static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category) {
List<DebuggerSettingsPanelProvider> providers = getSortedProviders();
if (providers.isEmpty()) {
return Collections.emptyList();
}
return providers.isEmpty() ? Collections.<Configurable>emptyList() : getConfigurables(category, providers);
}
List<Configurable> configurables = new SmartList<Configurable>();
@NotNull
static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category, @NotNull List<DebuggerSettingsPanelProvider> providers) {
List<Configurable> configurables = null;
for (DebuggerSettingsPanelProvider provider : providers) {
configurables.addAll(provider.getConfigurable(category));
Collection<? extends Configurable> providerConfigurables = provider.getConfigurable(category);
if (!providerConfigurables.isEmpty()) {
if (configurables == null) {
configurables = new SmartList<Configurable>();
}
configurables.addAll(providerConfigurables);
}
}
return configurables.isEmpty() ? Collections.<Configurable>emptyList() : configurables;
return ContainerUtil.isEmpty(configurables) ? Collections.<Configurable>emptyList() : configurables;
}
}
@@ -0,0 +1,54 @@
/*
* 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.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
class SteppingConfigurable extends SubCompositeConfigurable implements Configurable.NoScroll {
public SteppingConfigurable(@NotNull List<Configurable> configurables) {
assert !configurables.isEmpty();
children = configurables.toArray(new Configurable[configurables.size()]);
}
@NotNull
@Override
public String getId() {
return "debugger.stepping";
}
@Nls
@Override
public String getDisplayName() {
return XDebuggerBundle.message("debugger.stepping.display.name");
}
@Override
protected DataViewsConfigurableUi createRootUi() {
return null;
}
@NotNull
@Override
protected XDebuggerSettings.Category getCategory() {
return XDebuggerSettings.Category.STEPPING;
}
}
@@ -0,0 +1,178 @@
/*
* 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.ui.VerticalFlowLayout;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.xdebugger.impl.DebuggerSupport;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
abstract class SubCompositeConfigurable implements SearchableConfigurable.Parent {
protected DataViewsConfigurableUi root;
protected Configurable[] children;
protected JComponent rootComponent;
@Override
public boolean hasOwnContent() {
return getCategory() != XDebuggerSettings.Category.STEPPING;
}
@Override
public boolean isVisible() {
return true;
}
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
@Nullable
@Override
public String getHelpTopic() {
getConfigurables();
return children != null && children.length == 1 ? children[0].getHelpTopic() : null;
}
@Override
public final void disposeUIResources() {
root = null;
rootComponent = null;
if (isChildrenMerged()) {
for (Configurable child : children) {
child.reset();
}
}
children = null;
}
protected XDebuggerDataViewSettings getSettings() {
return null;
}
@Nullable
protected abstract DataViewsConfigurableUi createRootUi();
@NotNull
protected abstract XDebuggerSettings.Category getCategory();
private boolean isChildrenMerged() {
return children != null && (!getCategory().isSeparatePage() || children.length == 1);
}
@Override
public final Configurable[] getConfigurables() {
if (children == null) {
List<Configurable> configurables = DebuggerConfigurableProvider.getConfigurables(getCategory());
children = configurables.toArray(new Configurable[configurables.size()]);
}
return isChildrenMerged() ? DebuggerConfigurable.EMPTY_CONFIGURABLES : children;
}
@Nullable
@Override
public final JComponent createComponent() {
if (rootComponent == null) {
if (root == null) {
root = createRootUi();
}
getConfigurables();
if (isChildrenMerged()) {
if (children.length == 0) {
rootComponent = root == null ? null : root.getComponent();
}
else if (root == null && children.length == 1) {
rootComponent = children[0].createComponent();
}
else {
JPanel panel = new JPanel(new VerticalFlowLayout(0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET));
if (root != null) {
panel.add(root.getComponent());
}
for (Configurable child : children) {
JComponent component = child.createComponent();
if (component != null) {
component.setBorder(IdeBorderFactory.createTitledBorder(child.getDisplayName(), false));
panel.add(component);
}
}
rootComponent = panel;
}
}
else {
rootComponent = root == null ? null : root.getComponent();
}
}
return rootComponent;
}
@Override
public final void reset() {
if (root != null) {
root.reset(getSettings());
}
if (isChildrenMerged()) {
for (Configurable child : children) {
child.reset();
}
}
}
@Override
public final boolean isModified() {
if (root != null && root.isModified(getSettings())) {
return true;
}
else if (isChildrenMerged()) {
for (Configurable child : children) {
if (child.isModified()) {
return true;
}
}
}
return false;
}
@Override
public final void apply() throws ConfigurationException {
if (root != null) {
root.apply(getSettings());
for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
support.getSettingsPanelProvider().applied(getCategory());
}
}
if (isChildrenMerged()) {
for (Configurable child : children) {
if (child.isModified()) {
child.apply();
}
}
}
}
}
@@ -206,7 +206,6 @@ label.compound.renderer.configurable.table.header.name=Name
label.compound.renderer.configurable.table.header.expression=Expression
debugger.launching.configurable.display.name=Launching
debugger.hotswap.configurable.display.name=HotSwap
debugger.stepping.configurable.display.name=Stepping
label.debugger.launching.configurable.hide.window=Hide debug &window on process termination
label.debugger.focusAppOnBreakpoint=Focus application on breakpoint
label.debugger.hotswap.configurable.hotswap.background=Reload classes in &background