blob: 71c8634abe4193a2d01dd3eb5653fdd1e5fd9eeb [file] [log] [blame]
/*
* Copyright 2000-2013 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.breakpoints;
import com.intellij.icons.AllIcons;
import com.intellij.ide.favoritesTreeView.AbstractFavoritesListProvider;
import com.intellij.ide.favoritesTreeView.FavoritesManager;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.pom.Navigatable;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.CommonActionsPanel;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
import com.intellij.xdebugger.impl.DebuggerSupport;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
import com.intellij.xdebugger.impl.breakpoints.ui.tree.BreakpointItemsTreeController;
import com.intellij.xdebugger.impl.breakpoints.ui.tree.BreakpointsSimpleTree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.util.*;
import java.util.List;
/**
* User: Vassiliy.Kudryashov
*/
public class BreakpointsFavoriteListProvider extends AbstractFavoritesListProvider<Object>
implements BreakpointPanelProvider.BreakpointsListener {
private final List<BreakpointPanelProvider> myBreakpointPanelProviders;
private final BreakpointItemsTreeController myTreeController;
private final List<XBreakpointGroupingRule> myRulesAvailable = new ArrayList<XBreakpointGroupingRule>();
private Set<XBreakpointGroupingRule> myRulesEnabled = new TreeSet<XBreakpointGroupingRule>(XBreakpointGroupingRule.PRIORITY_COMPARATOR);
public BreakpointsFavoriteListProvider(Project project) {
super(project, "Breakpoints");
myBreakpointPanelProviders = XBreakpointUtil.collectPanelProviders();
myTreeController = new BreakpointItemsTreeController(myRulesAvailable);
myTreeController.setTreeView(new BreakpointsSimpleTree(myProject, myTreeController));
updateChildren();
for (final BreakpointPanelProvider provider : myBreakpointPanelProviders) {
provider.addListener(this, myProject, myProject);
provider.createBreakpointsGroupingRules(myRulesAvailable);
}
}
@Override
public void breakpointsChanged() {
updateChildren();
}
private void getEnabledGroupingRules(Collection<XBreakpointGroupingRule> rules) {
rules.clear();
XBreakpointsDialogState settings = ((XBreakpointManagerImpl)XDebuggerManager.getInstance(myProject).getBreakpointManager()).getBreakpointsDialogSettings();
for (XBreakpointGroupingRule rule : myRulesAvailable) {
if (rule.isAlwaysEnabled() || (settings != null && settings.getSelectedGroupingRules().contains(rule.getId()) ) ) {
rules.add(rule);
}
}
}
private void updateChildren() {
if (myProject.isDisposed()) return;
myChildren.clear();
List<BreakpointItem> items = new ArrayList<BreakpointItem>();
for (final BreakpointPanelProvider provider : myBreakpointPanelProviders) {
provider.provideBreakpointItems(myProject, items);
}
getEnabledGroupingRules(myRulesEnabled);
myTreeController.setGroupingRules(myRulesEnabled);
myTreeController.rebuildTree(items);
CheckedTreeNode root = myTreeController.getRoot();
for (int i = 0; i < root.getChildCount(); i++) {
TreeNode child = root.getChildAt(i);
if (child instanceof DefaultMutableTreeNode) {
replicate((DefaultMutableTreeNode)child, myNode, myChildren);
}
}
FavoritesManager.getInstance(myProject).fireListeners(getListName(myProject));
}
private void replicate(DefaultMutableTreeNode source, AbstractTreeNode destination, final List<AbstractTreeNode<Object>> destinationChildren) {
final ArrayList<AbstractTreeNode<Object>> copyChildren = new ArrayList<AbstractTreeNode<Object>>();
AbstractTreeNode<Object> copy = new AbstractTreeNode<Object>(myProject, source.getUserObject()) {
@NotNull
@Override
public Collection<? extends AbstractTreeNode> getChildren() {
return copyChildren;
}
@Override
protected void update(PresentationData presentation) {
}
};
for (int i = 0; i < source.getChildCount(); i++) {
final TreeNode treeNode = source.getChildAt(i);
if (treeNode instanceof DefaultMutableTreeNode) {
final DefaultMutableTreeNode sourceChild = (DefaultMutableTreeNode)treeNode;
replicate(sourceChild, copy, copyChildren);
}
}
if (checkNavigatable(copy)) {
destinationChildren.add(copy);
copy.setParent(destination);
}
}
private static boolean checkNavigatable(AbstractTreeNode<?> node) {
if (node.getValue() instanceof Navigatable && ((Navigatable)node.getValue()).canNavigate()) {
return true;
}
Collection<? extends AbstractTreeNode> children = node.getChildren();
for (AbstractTreeNode child : children) {
if (checkNavigatable(child)) {
return true;
}
}
return false;
}
@Nullable
@Override
public String getCustomName(@NotNull CommonActionsPanel.Buttons type) {
switch (type) {
case EDIT:
return "Edit breakpoint";
case REMOVE:
return "Remove breakpoint";
default:
return null;
}
}
@Override
public boolean willHandle(@NotNull CommonActionsPanel.Buttons type, Project project, @NotNull Set<Object> selectedObjects) {
return (selectedObjects.size() == 1 && (type == CommonActionsPanel.Buttons.EDIT || type == CommonActionsPanel.Buttons.REMOVE)) &&
((AbstractTreeNode)selectedObjects.iterator().next()).getValue() instanceof BreakpointItem;
}
@Override
public void handle(@NotNull CommonActionsPanel.Buttons type, Project project, @NotNull Set<Object> selectedObjects, JComponent component) {
Rectangle bounds = component.getBounds();
if (component instanceof JTree) {
JTree tree = (JTree)component;
bounds = tree.getRowBounds(tree.getLeadSelectionRow());
bounds.y += bounds.height/2;
bounds = tree.getVisibleRect().intersection(bounds);
}
Point whereToShow = new Point((int)bounds.getCenterX(), (int)bounds.getCenterY());
BreakpointItem breakpointItem = (BreakpointItem)((AbstractTreeNode)selectedObjects.iterator().next()).getValue();
switch (type) {
case EDIT:
DebuggerSupport debuggerSupport = XBreakpointUtil.getDebuggerSupport(myProject, breakpointItem);
if (debuggerSupport == null) return;
debuggerSupport.getEditBreakpointAction().editBreakpoint(myProject, component, whereToShow, breakpointItem);
break;
case REMOVE:
breakpointItem.removed(myProject);
break;
default: break;
}
}
@Override
public int getWeight() {
return BREAKPOINTS_WEIGHT;
}
@Override
public void customizeRenderer(ColoredTreeCellRenderer renderer,
JTree tree,
@NotNull Object value,
boolean selected,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
renderer.clear();
renderer.setIcon(AllIcons.Debugger.Db_set_breakpoint);
if (value instanceof BreakpointItem) {
BreakpointItem breakpointItem = (BreakpointItem)value;
breakpointItem.setupGenericRenderer(renderer, true);
}
else if (value instanceof XBreakpointGroup) {
renderer.append(((XBreakpointGroup)value).getName());
renderer.setIcon(((XBreakpointGroup)value).getIcon(expanded));
}
else if (value instanceof XBreakpointGroupingRule) {
renderer.append(((XBreakpointGroupingRule)value).getPresentableName());
}
else {
renderer.append(String.valueOf(value));
}
}
}