From a66b70ed42f2a58d4c811549c21fa33fce4692a6 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Fri, 8 Jun 2012 15:46:37 +0400 Subject: [PATCH] breakpoints ui. master breakpoint preview --- .../ui/breakpoints/BreakpointChooser.java | 223 ++++++++++++++++ .../BreakpointPropertiesPanel.java | 243 ++++++++---------- .../ui/breakpoints/JavaBreakpointItem.java | 28 +- .../intellij/ui/popup/util/DetailView.java | 66 ++++- .../intellij/ui/popup/util/ItemWrapper.java | 10 - .../intellij/ui/popup/util/SplitterItem.java | 5 - .../intellij/ide/bookmarks/BookmarkItem.java | 15 +- .../bookmarks/actions/BookmarksAction.java | 14 +- .../ui/popup/util/DetailViewImpl.java | 51 ++-- .../popup/util/MasterDetailPopupBuilder.java | 117 ++++++--- .../actionSystem/ex/ComboBoxAction.java | 5 +- .../intellij/openapi/ui/popup/ListPopup.java | 2 + .../intellij/ui/ColoredTreeCellRenderer.java | 6 +- .../intellij/ui/popup/list/ListPopupImpl.java | 1 + .../breakpoints/ui/BreakpointItem.java | 61 ++++- .../impl/breakpoints/XBreakpointItem.java | 37 +-- .../BreakpointsMasterDetailPopupFactory.java | 15 +- .../ui/tree/BreakpointItemNode.java | 33 +++ .../BreakpointItemsTreeController.java} | 103 +++----- .../BreakpointMasterDetailPopupBuilder.java | 203 ++++++++++----- .../ui/tree/BreakpointsCheckboxTree.java | 55 ++++ .../ui/tree/BreakpointsGroupNode.java | 39 +++ .../ui/tree/BreakpointsSimpleTree.java | 26 ++ .../ui/tree/BreakpointsTreeCellRenderer.java | 67 +++++ .../tasks/actions/SwitchTaskCombo.java | 4 +- .../actions/AbstractComboBoxAction.java | 3 +- 26 files changed, 1030 insertions(+), 402 deletions(-) create mode 100644 java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointChooser.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemNode.java rename platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/{BreakpointItemsTree.java => tree/BreakpointItemsTreeController.java} (74%) rename platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/{ => tree}/BreakpointMasterDetailPopupBuilder.java (58%) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsCheckboxTree.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsGroupNode.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsSimpleTree.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsTreeCellRenderer.java diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointChooser.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointChooser.java new file mode 100644 index 000000000000..3eaf0476498e --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointChooser.java @@ -0,0 +1,223 @@ +/* + * Copyright 2000-2012 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.debugger.ui.breakpoints; + +import com.intellij.debugger.DebuggerBundle; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; +import com.intellij.openapi.util.Key; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.breakpoints.ui.tree.BreakpointMasterDetailPopupBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Collection; + +public class BreakpointChooser { + private Project myProject; + + private DetailView myDetailView; + + private ActionToolbar myActionToolbar; + private BreakpointItem myBreakpointItem; + + private Delegate myDelegate; + private final ComboBoxAction myComboBoxAction; + private BreakpointMasterDetailPopupBuilder myPopupBuilder; + + private Object mySelectedBreakpoint; + + public void setDetailView(DetailView detailView) { + myDetailView = detailView; + } + + public Object getSelectedBreakpoint() { + return mySelectedBreakpoint; + } + + public BreakpointItem getBreakpointItem() { + return myBreakpointItem; + } + + public void setSelectedBreakpoint(Object selectedBreakpoint) { + mySelectedBreakpoint = selectedBreakpoint; + myBreakpointItem = selectedBreakpoint != null ? new JavaBreakpointItem(null, (Breakpoint)selectedBreakpoint) : null; + updatePresentation(myComboBoxAction.getTemplatePresentation(), myBreakpointItem); + myActionToolbar.getComponent().repaint(); + } + + private void pop(DetailView.PreviewEditorState pushed) { + if (pushed.getFile() != null) { + myDetailView + .navigateInPreviewEditor( + new DetailView.PreviewEditorState(pushed.getFile(), pushed.getNavigate(), pushed.getAttributes())); + } + else { + myDetailView.clearEditor(); + } + } + public interface Delegate { + void breakpointChosen(Project project, BreakpointItem breakpointItem, JBPopup popup); + } + + public BreakpointChooser(Project project, Delegate delegate) { + myProject = project; + myDelegate = delegate; + + myPopupBuilder = new BreakpointMasterDetailPopupBuilder(myProject); + myPopupBuilder.setPlainView(true); + + myComboBoxAction = new ComboBoxAction() { + + @Override + public void update(AnActionEvent e) { + final Presentation presentation = e.getPresentation(); + updatePresentation(presentation, BreakpointChooser.this.myBreakpointItem); + } + + @Override + protected ComboBoxButton createComboBoxButton(final Presentation presentation) { + return new ComboBoxButton(presentation) { + @Override + protected JBPopup createPopup(final Runnable onDispose) { + final DetailView.PreviewEditorState pushed = myDetailView.getEditorState(); + myPopupBuilder.setIsViewer(true); + myPopupBuilder.setAddDetailViewToEast(false); + myPopupBuilder.setDetailView(new MyDetailView(pushed)); + myPopupBuilder.setCallback(new BreakpointMasterDetailPopupBuilder.BreakpointChosenCallback() { + @Override + public void breakpointChosen(Project project, BreakpointItem breakpointItem, JBPopup popup) { + popup.cancel(); + myBreakpointItem = breakpointItem; + mySelectedBreakpoint = breakpointItem.getBreakpoint(); + updatePresentation(myComboBoxAction.getTemplatePresentation(), myBreakpointItem); + updatePresentation(presentation, myBreakpointItem); + + if (myDelegate != null) { + myDelegate.breakpointChosen(project, breakpointItem, popup); + } + } + }); + myPopupBuilder.setIsViewer(true); + JBPopup popup = myPopupBuilder.createPopup(); + popup.addListener(new JBPopupListener() { + @Override + public void beforeShown(LightweightWindowEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void onClosed(LightweightWindowEvent event) { + onDispose.run(); + pop(pushed); + } + }); + return popup; + } + + + }; + } + + @NotNull + @Override + protected DefaultActionGroup createPopupActionGroup(JComponent button) { + assert false : "should not be here"; + return null; + } + }; + + myActionToolbar = ActionManager.getInstance().createActionToolbar("asdad", new DefaultActionGroup(myComboBoxAction), true); + + } + + public void setBreakpointItems(Collection items) { + myPopupBuilder.setBreakpointItems(items); + } + + private void updatePresentation(Presentation presentation, BreakpointItem breakpointItem) { + if (breakpointItem != null) { + presentation.setIcon(breakpointItem.getIcon()); + presentation.setText(breakpointItem.getDisplayText()); + } + else { + presentation.setText(DebuggerBundle.message("value.none")); + } + + } + + public JComponent getComponent() { + return myActionToolbar.getComponent(); + } + + private class MyDetailView implements DetailView { + + private final PreviewEditorState myPushed; + + public MyDetailView(PreviewEditorState pushed) { + myPushed = pushed; + } + + @Override + public Editor getEditor() { + return myDetailView.getEditor(); + } + + @Override + public void navigateInPreviewEditor(PreviewEditorState editorState) { + if (myDetailView != null) { + myDetailView.navigateInPreviewEditor(editorState); + } + } + + @Override + public JPanel getDetailPanel() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void setDetailPanel(@Nullable JPanel panel) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void clearEditor() { + pop(myPushed); + } + + @Override + public PreviewEditorState getEditorState() { + return myDetailView.getEditorState(); + } + + @Override + public T getUserData(@NotNull Key key) { + return myDetailView.getUserData(key); + } + + @Override + public void putUserData(@NotNull Key key, @Nullable T value) { + myDetailView.putUserData(key, value); + } + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index 9dea6960a3ac..ce2bc0a5a938 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -20,7 +20,6 @@ */ package com.intellij.debugger.ui.breakpoints; -import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.InstanceFilter; import com.intellij.debugger.engine.evaluation.CodeFragmentKind; @@ -30,12 +29,12 @@ import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.ui.CompletionEditor; import com.intellij.debugger.ui.DebuggerExpressionComboBox; import com.intellij.debugger.ui.DebuggerStatementEditor; -import com.intellij.ui.ListCellRendererWrapper; +import com.intellij.debugger.ui.JavaDebuggerSupport; import com.intellij.ide.util.ClassFilter; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.FixedSizeButton; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; @@ -44,7 +43,10 @@ import com.intellij.psi.PsiElement; import com.intellij.ui.FieldPanel; import com.intellij.ui.MultiLineTooltipUI; import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.popup.util.DetailView; import com.intellij.util.IJSwingUtilities; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -58,6 +60,16 @@ import java.util.Iterator; import java.util.List; public abstract class BreakpointPropertiesPanel { + + private final BreakpointChooser myMasterBreakpointChooser; + + public void setDetailView(DetailView detailView) { + myDetailView = detailView; + myMasterBreakpointChooser.setDetailView(detailView); + } + + private DetailView myDetailView; + protected final Project myProject; private final Key myBreakpointCategory; private boolean myCompact; @@ -104,7 +116,6 @@ public abstract class BreakpointPropertiesPanel { ButtonGroup mySuspendPolicyGroup; @NonNls public static final String CONTROL_LOG_MESSAGE = "logMessage"; - private BreakpointComboboxHandler myBreakpointComboboxHandler; private static final int MAX_COMBO_WIDTH = 300; private final FixedSizeButton myConditionMagnifierButton; private boolean myMoreOptionsVisible = true; @@ -139,6 +150,10 @@ public abstract class BreakpointPropertiesPanel { }; } + public DetailView getDetailView() { + return myDetailView; + } + public interface Delegate { void showActionsPanel(); @@ -153,10 +168,6 @@ public abstract class BreakpointPropertiesPanel { } public void dispose() { - if (myBreakpointComboboxHandler != null) { - myBreakpointComboboxHandler.dispose(); - myBreakpointComboboxHandler = null; - } if (myConditionCombo != null) { myConditionCombo.dispose(); } @@ -212,7 +223,7 @@ public abstract class BreakpointPropertiesPanel { panel.add(component, BorderLayout.CENTER); } - public BreakpointPropertiesPanel(Project project, final Key breakpointCategory, boolean compact) { + public BreakpointPropertiesPanel(final Project project, final Key breakpointCategory, boolean compact) { myProject = project; myBreakpointCategory = breakpointCategory; myCompact = compact; @@ -226,7 +237,7 @@ public abstract class BreakpointPropertiesPanel { public void itemStateChanged(final ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { final String defaultPolicy = - DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().getDefaultSuspendPolicy(breakpointCategory); + getBreakpointManager(myProject).getDefaultSuspendPolicy(breakpointCategory); myMakeDefaultButton.setEnabled(!defaultPolicy.equals(getSelectedSuspendPolicy())); } } @@ -247,7 +258,7 @@ public abstract class BreakpointPropertiesPanel { myMakeDefaultButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager(); + final BreakpointManager breakpointManager = getBreakpointManager(myProject); final String suspendPolicy = getSelectedSuspendPolicy(); breakpointManager.setDefaultSuspendPolicy(breakpointCategory, suspendPolicy); updateSuspendPolicyRbFont(); @@ -272,20 +283,25 @@ public abstract class BreakpointPropertiesPanel { } myLogExpressionCombo = new DebuggerExpressionComboBox(project, "LineBreakpoint logMessage"); - - final ComboBox baseBreakpointCombo = new ComboBox(100); - myBreakpointComboboxHandler = new BreakpointComboboxHandler(myProject, baseBreakpointCombo); - baseBreakpointCombo.setRenderer(new BreakpointComboRenderer(baseBreakpointCombo.getRenderer())); - baseBreakpointCombo.addItemListener(new ItemListener() { - public void itemStateChanged(final ItemEvent e) { - ComboboxItem item = (ComboboxItem)baseBreakpointCombo.getSelectedItem(); + myMasterBreakpointChooser = new BreakpointChooser(project, new BreakpointChooser.Delegate() { + @Override + public void breakpointChosen(Project project, BreakpointItem item, JBPopup popup) { final boolean enabled = item != null && item.getBreakpoint() != null; myLeaveEnabledRadioButton.setEnabled(enabled); myDisableAgainRadio.setEnabled(enabled); myEnableOrDisableLabel.setEnabled(enabled); + + if (item != null) { + + saveMasterBreakpoint(); + } + + updateMasterBreakpointPanel(findMasterBreakpointRule()); + } }); + myInstanceFiltersField = new FieldPanel(new MyTextField(), "", null, new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -341,7 +357,8 @@ public abstract class BreakpointPropertiesPanel { insert(myConditionComboPanel, conditionPanel); insert(myLogExpressionComboPanel, myLogExpressionCombo); - insert(myDependentBreakpointComboPanel, baseBreakpointCombo); + //insert(myDependentBreakpointComboPanel, baseBreakpointCombo); + insert(myDependentBreakpointComboPanel, myMasterBreakpointChooser.getComponent()); insert(myInstanceFiltersFieldPanel, myInstanceFiltersField); insert(myClassFiltersFieldPanel, myClassFiltersField); @@ -364,6 +381,51 @@ public abstract class BreakpointPropertiesPanel { IJSwingUtilities.adjustComponentsOnMac(myLogMessageCheckBox); } + private List getBreakpointItemsExceptMy() { + List items = new ArrayList(); + findJavaDebuggerSupport().getBreakpointPanelProvider().provideBreakpointItems(myProject, items); + for (BreakpointItem item : items) { + if (item.getBreakpoint() == myBreakpoint) { + items.remove(item); + break; + } + } + return items; + } + + private DebuggerSupport findJavaDebuggerSupport() { + DebuggerSupport[] supports = DebuggerSupport.getDebuggerSupports(); + DebuggerSupport support = null; + for (DebuggerSupport s : supports) { + if (s instanceof JavaDebuggerSupport) { + support = s; + } + } + return support; + } + + private void saveMasterBreakpoint() { + + + Breakpoint masterBreakpoint = (Breakpoint)myMasterBreakpointChooser.getSelectedBreakpoint(); + if (masterBreakpoint == null) { + getBreakpointManager(myProject).removeBreakpointRule(myBreakpoint); + } + else { + EnableBreakpointRule rule = findMasterBreakpointRule(); + boolean selected = myLeaveEnabledRadioButton.isSelected(); + if (rule != null && (rule.getMasterBreakpoint() != masterBreakpoint || rule.isLeaveEnabled() != selected ) ) { + getBreakpointManager(myProject).removeBreakpointRule(rule); + + } + getBreakpointManager(myProject).addBreakpointRule(new EnableBreakpointRule(getBreakpointManager(myProject), + masterBreakpoint, + myBreakpoint, + selected)); + } + + } + private String getSelectedSuspendPolicy() { if (!mySuspendJBCheckBox.isSelected()) { return DebuggerSettings.SUSPEND_NONE; @@ -375,7 +437,7 @@ public abstract class BreakpointPropertiesPanel { } private void updateSuspendPolicyRbFont() { - final String defPolicy = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().getDefaultSuspendPolicy(myBreakpointCategory); + final String defPolicy = getBreakpointManager(myProject).getDefaultSuspendPolicy(myBreakpointCategory); final Font font = mySuspendAllRadio.getFont().deriveFont(Font.PLAIN); final Font boldFont = font.deriveFont(Font.BOLD); @@ -410,7 +472,9 @@ public abstract class BreakpointPropertiesPanel { myBreakpoint = breakpoint; boolean moreOptionsVisible = moreOptionsVisible1; boolean actionsPanelVisible = moreOptionsVisible1; - myBreakpointComboboxHandler.initFrom(breakpoint); + + initMasterBreakpointPanel(); + if (breakpoint.COUNT_FILTER > 0) { myPassCountField.setText(Integer.toString(breakpoint.COUNT_FILTER)); moreOptionsVisible = true; @@ -504,6 +568,31 @@ public abstract class BreakpointPropertiesPanel { setMoreOptionsVisible(moreOptionsVisible); } + private void initMasterBreakpointPanel() { + myMasterBreakpointChooser.setBreakpointItems(getBreakpointItemsExceptMy()); + + final EnableBreakpointRule rule = findMasterBreakpointRule(); + + final Breakpoint baseBreakpoint = rule != null ? rule.getMasterBreakpoint() : null; + updateMasterBreakpointPanel(rule); + + myMasterBreakpointChooser.setSelectedBreakpoint(baseBreakpoint); + } + + private @Nullable EnableBreakpointRule findMasterBreakpointRule() { + return myBreakpoint != null? getBreakpointManager(myProject).findBreakpointRule(myBreakpoint) : null; + } + + private void updateMasterBreakpointPanel(@Nullable EnableBreakpointRule rule) { + final boolean leaveEnabled = rule != null && rule.isLeaveEnabled(); + if (leaveEnabled) { + myLeaveEnabledRadioButton.setSelected(true); + } + else { + myDisableAgainRadio.setSelected(true); + } + } + private TextWithImportsImpl emptyText() { return new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, ""); } @@ -512,7 +601,8 @@ public abstract class BreakpointPropertiesPanel { * Save values in the UI components to the breakpoint object */ public void saveTo(Breakpoint breakpoint, @NotNull Runnable afterUpdate) { - myBreakpointComboboxHandler.saveTo(breakpoint, myLeaveEnabledRadioButton.isSelected()); + + saveMasterBreakpoint(); try { String text = myPassCountField.getText().trim(); int count = !"".equals(text)? Integer.parseInt(text) : 0; @@ -702,37 +792,6 @@ public abstract class BreakpointPropertiesPanel { public JPanel getPanel() { return myPanel; } - - private static class BreakpointComboboxModel extends DefaultComboBoxModel { - private final ComboboxItem[] myItems; - - public BreakpointComboboxModel(Breakpoint[] breakpoints) { - myItems = new ComboboxItem[breakpoints.length + 1]; - myItems[0] = new ComboboxItem(); - for (int idx = 0; idx < breakpoints.length; idx++) { - myItems[idx + 1] = new ComboboxItem(breakpoints[idx]); - } - } - - public int getSize() { - return myItems.length; - } - - public ComboboxItem getElementAt(int index) { - return myItems[index]; - } - - public void selectBreakpoint(Breakpoint breakpoint) { - for (final ComboboxItem item : myItems) { - if (breakpoint == null ? item.getBreakpoint() == null : breakpoint.equals(item.getBreakpoint())) { - if (!item.equals(getSelectedItem())) { - setSelectedItem(item); - } - break; - } - } - } - } private static class ComboboxItem { private final Breakpoint breakpoint; @@ -764,83 +823,9 @@ public abstract class BreakpointPropertiesPanel { return breakpoint != null ? breakpoint.hashCode() : 0; } } - - private class BreakpointComboboxHandler implements BreakpointManagerListener{ - private final JComboBox myCombo; - private final BreakpointManager myBreakpointManager; - private Breakpoint myCurrentBreakpoint = null; - public BreakpointComboboxHandler(final Project project, final JComboBox breakpointCombo) { - myCombo = breakpointCombo; - myBreakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager(); - myBreakpointManager.addBreakpointManagerListener(this); - } - - public void initFrom(Breakpoint breakpoint) { - myCurrentBreakpoint = breakpoint; - fillCombobox(); - } - - public void saveTo(Breakpoint slaveBreakpoint, final boolean leaveEnabled) { - myBreakpointManager.removeBreakpointRule(slaveBreakpoint); - final Breakpoint masterBreakpoint = ((ComboboxItem)myCombo.getSelectedItem()).getBreakpoint(); - if (masterBreakpoint != null) { - myBreakpointManager.addBreakpointRule(new EnableBreakpointRule(myBreakpointManager, masterBreakpoint, slaveBreakpoint, leaveEnabled)); - } - } - - public void breakpointsChanged() { - fillCombobox(); - } - - public void dispose() { - myBreakpointManager.removeBreakpointManagerListener(this); - } - - private void fillCombobox() { - final List breakpoints = new ArrayList(myBreakpointManager.getBreakpoints()); - if (myCurrentBreakpoint != null) { - // avoid depending on itself - breakpoints.remove(myCurrentBreakpoint); - } - myCombo.setModel(new BreakpointComboboxModel(breakpoints.toArray(new Breakpoint[breakpoints.size()]))); - final EnableBreakpointRule rule = myCurrentBreakpoint != null? myBreakpointManager.findBreakpointRule(myCurrentBreakpoint) : null; - final Breakpoint baseBreakpoint = rule != null? rule.getMasterBreakpoint() : null; - final boolean leaveEnabled = rule != null && rule.isLeaveEnabled(); - if (leaveEnabled) { - myLeaveEnabledRadioButton.setSelected(true); - } - else { - myDisableAgainRadio.setSelected(true); - } - ((BreakpointComboboxModel)myCombo.getModel()).selectBreakpoint(baseBreakpoint); - } - } - - private static class BreakpointComboRenderer extends ListCellRendererWrapper { - public BreakpointComboRenderer(final ListCellRenderer listCellRenderer) { - super(listCellRenderer); - } - - @Override - public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { - Breakpoint breakpoint = ((ComboboxItem)value).getBreakpoint(); - final String text = breakpoint != null ? index == -1 ? breakpoint.getShortName() : breakpoint.getDisplayName() : DebuggerBundle.message("value.none"); - setText(text); - - final Icon icon; - if (breakpoint != null) { - icon = breakpoint instanceof BreakpointWithHighlighter - ? breakpoint.ENABLED - ? ((BreakpointWithHighlighter)breakpoint).getSetIcon(false) - : ((BreakpointWithHighlighter)breakpoint).getDisabledIcon(false) - : breakpoint.getIcon(); - } - else { - icon = null; - } - setIcon(icon); - } + private BreakpointManager getBreakpointManager(Project project) { + return DebuggerManagerEx.getInstanceEx(project).getBreakpointManager(); } private static class MagnifierButtonAction implements ActionListener { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index a186926b531b..170eec164c2f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -23,6 +23,7 @@ import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.popup.util.DetailView; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -37,17 +38,29 @@ class JavaBreakpointItem extends BreakpointItem { private final Breakpoint myBreakpoint; private BreakpointFactory myBreakpointFactory; - public JavaBreakpointItem(BreakpointFactory breakpointFactory, Breakpoint breakpoint) { + public JavaBreakpointItem(@Nullable BreakpointFactory breakpointFactory, Breakpoint breakpoint) { myBreakpointFactory = breakpointFactory; myBreakpoint = breakpoint; } @Override - protected void setupGenericRenderer(SimpleColoredComponent renderer) { - //renderer.setIcon(myBreakpoint.getIcon()); + protected void setupGenericRenderer(SimpleColoredComponent renderer, boolean plainView) { + if (plainView) { + renderer.setIcon(myBreakpoint.getIcon()); + } renderer.append(myBreakpoint.getShortName(), isEnabled() ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES); } + @Override + public Icon getIcon() { + return myBreakpoint.getIcon(); + } + + @Override + public String getDisplayText() { + return myBreakpoint.getDisplayName(); + } + @Override public String speedSearchText() { return myBreakpoint.getDisplayName(); @@ -59,11 +72,12 @@ class JavaBreakpointItem extends BreakpointItem { } @Override - public void updateDetailView(DetailView panel) { - BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory - .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); + protected void doUpdateDetailView(DetailView panel) { + BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory != null ? myBreakpointFactory + .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false) : null; if (breakpointPropertiesPanel != null) { breakpointPropertiesPanel.setSaveOnRemove(true); + breakpointPropertiesPanel.setDetailView(panel); } if (breakpointPropertiesPanel != null) { @@ -86,7 +100,7 @@ class JavaBreakpointItem extends BreakpointItem { @Override public boolean allowedToRemove() { - return myBreakpointFactory.breakpointCanBeRemoved(myBreakpoint); + return myBreakpointFactory != null && myBreakpointFactory.breakpointCanBeRemoved(myBreakpoint); } @Override diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java index f065366ab209..c195f9789f62 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java @@ -18,6 +18,7 @@ package com.intellij.ui.popup.util; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; @@ -30,16 +31,75 @@ import javax.swing.*; * Time: 5:34 AM * To change this template use File | Settings | File Templates. */ -public interface DetailView { - void updateWithItem(ItemWrapper wrapper); +public interface DetailView extends UserDataHolder { Editor getEditor(); - void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate, TextAttributes lineAttributes); + void navigateInPreviewEditor(PreviewEditorState editorState); JPanel getDetailPanel(); void setDetailPanel(@Nullable JPanel panel); void clearEditor(); + + PreviewEditorState getEditorState(); + + class PreviewEditorState { + + public static PreviewEditorState EMPTY = new PreviewEditorState(null, null, null); + + public static PreviewEditorState create(VirtualFile file, int line) { + return new PreviewEditorState(file, new LogicalPosition(line, 0), null); + } + + public static PreviewEditorState create(VirtualFile file, int line, TextAttributes attributes) { + return new PreviewEditorState(file, new LogicalPosition(line, 0), attributes); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PreviewEditorState state = (PreviewEditorState)o; + + if (myAttributes != null ? !myAttributes.equals(state.myAttributes) : state.myAttributes != null) return false; + if (myFile != null ? !myFile.equals(state.myFile) : state.myFile != null) return false; + if (myNavigate != null ? !myNavigate.equals(state.myNavigate) : state.myNavigate != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myFile != null ? myFile.hashCode() : 0; + result = 31 * result + (myNavigate != null ? myNavigate.hashCode() : 0); + result = 31 * result + (myAttributes != null ? myAttributes.hashCode() : 0); + return result; + } + + public VirtualFile getFile() { + return myFile; + } + + public LogicalPosition getNavigate() { + return myNavigate; + } + + public TextAttributes getAttributes() { + return myAttributes; + } + + private final VirtualFile myFile; + private final LogicalPosition myNavigate; + private final TextAttributes myAttributes; + + public PreviewEditorState(VirtualFile file, LogicalPosition navigate, TextAttributes attributes) { + + myFile = file; + myNavigate = navigate; + myAttributes = attributes; + } + } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java index a84bac7f454d..c1c4d0bcc221 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -16,20 +16,12 @@ package com.intellij.ui.popup.util; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.ColoredTreeCellRenderer; import org.jetbrains.annotations.Nullable; import javax.swing.*; -/** -* Created with IntelliJ IDEA. -* User: zajac -* Date: 5/6/12 -* Time: 2:05 AM -* To change this template use File | Settings | File Templates. -*/ public interface ItemWrapper { void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); @@ -37,8 +29,6 @@ public interface ItemWrapper { void updateAccessoryView(JComponent label); - void execute(Project project, JBPopup popup); - String speedSearchText(); @Nullable diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java index 4c038b103861..1b3bf2bd64cc 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java @@ -56,11 +56,6 @@ public class SplitterItem implements ItemWrapper { //To change body of implemented methods use File | Settings | File Templates. } - @Override - public void execute(Project project, JBPopup popup) { - //To change body of implemented methods use File | Settings | File Templates. - } - @Override public String speedSearchText() { return ""; //To change body of implemented methods use File | Settings | File Templates. diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java index 68151a1dfc01..75d3dd2da9fa 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -15,11 +15,9 @@ */ package com.intellij.ide.bookmarks; -import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; @@ -110,22 +108,17 @@ public class BookmarkItem implements ItemWrapper { return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); } - public void execute(Project project, JBPopup popup) { - popup.cancel(); - myBookmark.navigate(); - popup.cancel(); - } - public String footerText() { return myBookmark.getFile().getPresentableUrl(); } @Override public void updateDetailView(final DetailView panel) { - VirtualFile file = myBookmark.getFile(); - LogicalPosition positionToNavigate = new LogicalPosition(myBookmark.getLine(), 0); + doUpdateDetailView(panel); + } - panel.navigateInPreviewEditor(file, positionToNavigate, null); + private void doUpdateDetailView(DetailView panel) { + panel.navigateInPreviewEditor(DetailView.PreviewEditorState.create(myBookmark.getFile(), myBookmark.getLine())); } @Override diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 70875e35aa49..4e513fad4c78 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -23,7 +23,8 @@ import com.intellij.ide.bookmarks.Bookmark; import com.intellij.ide.bookmarks.BookmarkItem; import com.intellij.ide.bookmarks.BookmarkManager; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; @@ -32,6 +33,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.util.DetailViewImpl; +import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.ui.speedSearch.FilteringListModel; import org.jetbrains.annotations.Nullable; @@ -121,6 +124,15 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail return new Object[0]; //To change body of implemented methods use File | Settings | File Templates. } + @Override + public void itemChosen(ItemWrapper item, Project project, JBPopup popup) { + if (item instanceof BookmarkItem) { + Bookmark bookmark = ((BookmarkItem)item).getBookmark(); + popup.cancel(); + bookmark.navigate(); + } + } + private static DefaultListModel buildModel(Project project) { final DefaultListModel model = new DefaultListModel(); diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index 4327addc74c9..494b1d649b3d 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -26,8 +26,12 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBScrollPane; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -40,7 +44,7 @@ import java.awt.*; * Time: 2:04 AM * To change this template use File | Settings | File Templates. */ -public class DetailViewImpl extends JPanel implements DetailView { +public class DetailViewImpl extends JPanel implements DetailView, UserDataHolder { private final Project myProject; private Editor myEditor; private ItemWrapper myWrapper; @@ -51,6 +55,7 @@ public class DetailViewImpl extends JPanel implements DetailView { private JLabel myNothingToShow = new JLabel("Nothing to show"); private JLabel myNothingToShowInEditor = new JLabel("Nothing to show"); private RangeHighlighter myHighlighter; + private PreviewEditorState myEditorState = PreviewEditorState.EMPTY; public DetailViewImpl(Project project) { super(new BorderLayout()); @@ -60,34 +65,24 @@ public class DetailViewImpl extends JPanel implements DetailView { myNothingToShowInEditor.setHorizontalAlignment(JLabel.CENTER); } - @Override - public void updateWithItem(ItemWrapper wrapper) { - if (myWrapper != wrapper) { - myWrapper = wrapper; - if (wrapper != null) { - wrapper.updateDetailView(this); - } - else { - clearEditor(); - repaint(); - } - - revalidate(); - } - } - @Override public void clearEditor() { if (getEditor() != null) { clearHightlighting(); remove(getEditor().getComponent()); EditorFactory.getInstance().releaseEditor(getEditor()); + myEditorState = PreviewEditorState.EMPTY; setEditor(null); add(myNothingToShowInEditor, BorderLayout.CENTER); repaint(); } } + @Override + public PreviewEditorState getEditorState() { + return myEditorState; + } + @Override public void removeNotify() { super.removeNotify(); @@ -104,7 +99,12 @@ public class DetailViewImpl extends JPanel implements DetailView { } @Override - public void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate, @Nullable TextAttributes lineAttributes) { + public void navigateInPreviewEditor(PreviewEditorState editorState) { + myEditorState = editorState; + + final VirtualFile file = editorState.getFile(); + final LogicalPosition positionToNavigate = editorState.getNavigate(); + final TextAttributes lineAttributes = editorState.getAttributes(); Document document = FileDocumentManager.getInstance().getDocument(file); Project project = myProject; @@ -134,10 +134,9 @@ public class DetailViewImpl extends JPanel implements DetailView { getEditor().getScrollingModel().scrollToCaret(ScrollType.CENTER); clearHightlighting(); - if (lineAttributes != null){ + if (lineAttributes != null) { myHighlighter = getEditor().getMarkupModel().addLineHighlighter(positionToNavigate.line, HighlighterLayer.SELECTION - 1, lineAttributes); - } } else { @@ -188,4 +187,16 @@ public class DetailViewImpl extends JPanel implements DetailView { } myDetailPanel = panel; } + + final UserDataHolderBase myDataHolderBase = new UserDataHolderBase(); + + @Override + public T getUserData(@NotNull Key key) { + return myDataHolderBase.getUserData(key); + } + + @Override + public void putUserData(@NotNull Key key, @Nullable T value) { + myDataHolderBase.putUserData(key, value); + } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 257197ead096..de8a4ae7408b 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -20,6 +20,8 @@ import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.ColoredListCellRenderer; @@ -42,13 +44,6 @@ import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; -/** - * Created with IntelliJ IDEA. - * User: zajac - * Date: 5/6/12 - * Time: 2:06 PM - * To change this template use File | Settings | File Templates. - */ public class MasterDetailPopupBuilder { private static final Color BORDER_COLOR = Gray._135; @@ -57,26 +52,27 @@ public class MasterDetailPopupBuilder { private Delegate myDelegate; private boolean myCloseOnEnter; - public DetailViewImpl getDetailView() { - return myDetailView; - } + private DetailView myDetailView; - private DetailViewImpl myDetailView; private JLabel myPathLabel; + private JBPopup myPopup; private Alarm myUpdateAlarm; - - private JComponent myChooserComponent; + private ActionToolbar myActionToolbar; + private boolean myAddDetailViewToEast; + + + public MasterDetailPopupBuilder setDetailView(DetailView detailView) { + myDetailView = detailView; + return this; + } public ActionToolbar getActionToolbar() { return myActionToolbar; } - private ActionToolbar myActionToolbar; - public MasterDetailPopupBuilder(Project project) { - myProject = project; } @@ -106,11 +102,20 @@ public class MasterDetailPopupBuilder { myUpdateAlarm.cancelAllRequests(); myUpdateAlarm.addRequest(new Runnable() { public void run() { - myDetailView.updateWithItem(wrapper1); + doUpdateDetailViewWithItem(wrapper1); } }, 100); } + protected void doUpdateDetailViewWithItem(ItemWrapper wrapper1) { + if (wrapper1 != null) { + wrapper1.updateDetailView(myDetailView); + } + else { + myDetailView.clearEditor(); + } + } + public JBPopup createMasterDetailPopup() { setupRenderer(); @@ -122,7 +127,10 @@ public class MasterDetailPopupBuilder { myPathLabel.setFont(font.deriveFont((float)10)); myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - myDetailView = new DetailViewImpl(myProject); + + if (myDetailView == null) { + myDetailView = new DetailViewImpl(myProject); + } JPanel footerPanel = new JPanel(new BorderLayout()) { @Override @@ -139,14 +147,13 @@ public class MasterDetailPopupBuilder { IdeFocusManager.getInstance(myProject).doWhenFocusSettlesDown(new Runnable() { public void run() { Object[] values = getSelectedItems(); - if (values.length == 1) { - ((ItemWrapper)values[0]).execute(myProject, myPopup); + myDelegate.itemChosen((ItemWrapper)values[0], myProject, myPopup); } else { for (Object value : values) { if (value instanceof ItemWrapper) { - ((ItemWrapper)value).execute(myProject, myPopup); + myDelegate.itemChosen((ItemWrapper)value, myProject, myPopup); } } } @@ -158,21 +165,34 @@ public class MasterDetailPopupBuilder { footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); footerPanel.add(myPathLabel); - myActionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); - myActionToolbar.setReservePlaceAutoPopupIcon(false); - myActionToolbar.setMinimumButtonSize(new Dimension(20, 20)); - final JComponent toolBar = myActionToolbar.getComponent(); - toolBar.setOpaque(false); + JComponent toolBar = null; + if (myActions != null) { + myActionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); + myActionToolbar.setReservePlaceAutoPopupIcon(false); + myActionToolbar.setMinimumButtonSize(new Dimension(20, 20)); + toolBar = myActionToolbar.getComponent(); + toolBar.setOpaque(false); + } - final PopupChooserBuilder builder = createInnerBuilder(); - myPopup = builder. - setTitle(myDelegate.getTitle()). + final PopupChooserBuilder builder = createInnerBuilder(). setMovable(true). setResizable(true). setAutoselectOnMouseMove(false). setSettingButton(toolBar). - setSouthComponent(footerPanel). - setEastComponent(myDetailView). + setSouthComponent(footerPanel); + + if (myAddDetailViewToEast) { + builder. + setEastComponent((JComponent)myDetailView); + } + + String title = myDelegate.getTitle(); + if (title != null) { + builder.setTitle(title); + } + + + builder. setItemChoosenCallback(runnable). setCloseOnEnter(myCloseOnEnter). setMayBeParent(true). @@ -181,7 +201,20 @@ public class MasterDetailPopupBuilder { public String fun(Object o) { return ((ItemWrapper)o).speedSearchText(); } - }).createPopup(); + }); + + myPopup = builder.createPopup(); + myPopup.addListener(new JBPopupListener() { + @Override + public void beforeShown(LightweightWindowEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void onClosed(LightweightWindowEvent event) { + myDetailView.clearEditor(); + } + }); return myPopup; } @@ -214,11 +247,16 @@ public class MasterDetailPopupBuilder { private void updateDetailViewLater() { //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - public void run() { - doUpdateDetailView(); - } - }); + //SwingUtilities.invokeLater(new Runnable() { + // public void run() { + // doUpdateDetailView(); + // } + //}); + doUpdateDetailView(); + } + + public void setAddDetailViewToEast(boolean addDetailViewToEast) { + myAddDetailViewToEast = addDetailViewToEast; } public static boolean allowedToRemoveItems(Object[] values) { @@ -271,7 +309,7 @@ public class MasterDetailPopupBuilder { } } - public MasterDetailPopupBuilder setActionsGroup(ActionGroup actions) { + public MasterDetailPopupBuilder setActionsGroup(@Nullable ActionGroup actions) { myActions = actions; return this; } @@ -332,6 +370,7 @@ public class MasterDetailPopupBuilder { } public interface Delegate { + @Nullable String getTitle(); void handleMnemonic(KeyEvent e, Project project, JBPopup popup); @@ -340,6 +379,8 @@ public class MasterDetailPopupBuilder { JComponent createAccessoryView(Project project); Object[] getSelectedItemsInTree(); + + void itemChosen(ItemWrapper item, Project project, JBPopup popup); } public static class ListItemRenderer extends JPanel implements ListCellRenderer { diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java index 5034dddbc5c7..249c8321b92b 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java @@ -18,6 +18,7 @@ package com.intellij.openapi.actionSystem.ex; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.IconLoader; @@ -160,7 +161,7 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent } }; - ListPopup popup = createPopup(onDispose); + JBPopup popup = createPopup(onDispose); popup.show(new RelativePoint(this, new Point(0, this.getHeight() - 1))); } @@ -171,7 +172,7 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent return myForcePressed ? null : super.getToolTipText(); } - protected ListPopup createPopup(Runnable onDispose) { + protected JBPopup createPopup(Runnable onDispose) { DefaultActionGroup group = createPopupActionGroup(this); DataContext context = getDataContext(); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopup.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopup.java index 86ff18f455ad..df8c5b042043 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopup.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopup.java @@ -16,6 +16,7 @@ package com.intellij.openapi.ui.popup; +import javax.swing.event.ListSelectionListener; import java.awt.event.InputEvent; /** @@ -52,4 +53,5 @@ public interface ListPopup extends JBPopup { */ void setHandleAutoSelectionBeforeShow(boolean autoHandle); + void addListSelectionListener(ListSelectionListener listSelectionListener); } diff --git a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java index 73122be7dae5..afb002e73bb5 100644 --- a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java @@ -41,8 +41,8 @@ public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent imp protected boolean myFocused; protected JTree myTree; - private boolean myOpaque = true; + private boolean myOpaque = true; public final Component getTreeCellRendererComponent( JTree tree, Object value, @@ -122,6 +122,10 @@ public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent imp return this; } + public JTree getTree() { + return myTree; + } + protected boolean isFocused() { return myTree.hasFocus(); } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java index ba29b515cea4..29455c59589b 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/list/ListPopupImpl.java @@ -364,6 +364,7 @@ public class ListPopupImpl extends WizardPopup implements ListPopup { } + @Override public void addListSelectionListener(ListSelectionListener listSelectionListener) { myList.addListSelectionListener(listSelectionListener); } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java index 82abf3ad6522..c8d0ac85aaa8 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -16,14 +16,13 @@ package com.intellij.xdebugger.breakpoints.ui; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.MarkupModel; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ColorUtil; import com.intellij.ui.ColoredListCellRenderer; @@ -43,17 +42,25 @@ import javax.swing.*; * To change this template use File | Settings | File Templates. */ public abstract class BreakpointItem implements ItemWrapper { + protected static final Key BREAKPOINT_ITEM = Key.create("BreakpointItem"); + public abstract Object getBreakpoint(); public abstract boolean isEnabled(); public abstract void setEnabled(boolean state); - protected void showInEditor(DetailView panel, VirtualFile virtualFile, int line) { + protected boolean showInEditor(DetailView panel, VirtualFile virtualFile, int line) { TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES); - panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(line, 0), attributes); + DetailView.PreviewEditorState state = DetailView.PreviewEditorState.create(virtualFile, line, attributes); + + if (state.equals(panel.getEditorState())) { + return false; + } + + panel.navigateInPreviewEditor(state); TextAttributes softerAttributes = attributes.clone(); softerAttributes.setBackgroundColor(ColorUtil.softer(softerAttributes.getBackgroundColor())); @@ -72,10 +79,7 @@ public abstract class BreakpointItem implements ItemWrapper { } } } - } - - @Override - public void execute(Project project, JBPopup popup) { + return true; } @Override @@ -86,14 +90,49 @@ public abstract class BreakpointItem implements ItemWrapper { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - setupGenericRenderer(renderer); + setupGenericRenderer(renderer, true); } @Override public void setupRenderer(ColoredTreeCellRenderer renderer) { - setupGenericRenderer(renderer); + boolean plainView = renderer.getTree().getClientProperty("plainView") != null; + setupGenericRenderer(renderer, plainView); } - protected abstract void setupGenericRenderer(SimpleColoredComponent renderer); + @Override + public void updateDetailView(DetailView panel) { + if (panel.getUserData(BREAKPOINT_ITEM) == getBreakpoint()) { + return; + } + + doUpdateDetailView(panel); + + panel.putUserData(BREAKPOINT_ITEM, getBreakpoint()); + } + + protected abstract void setupGenericRenderer(SimpleColoredComponent renderer, boolean plainView); + + public abstract Icon getIcon(); + + public abstract String getDisplayText(); + + protected abstract void doUpdateDetailView(DetailView panel); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + BreakpointItem item = (BreakpointItem)o; + + if (getBreakpoint() != null ? !getBreakpoint().equals(item.getBreakpoint()) : item.getBreakpoint() != null) return false; + + return true; + } + + @Override + public int hashCode() { + return getBreakpoint() != null ? getBreakpoint().hashCode() : 0; + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index 3df95722ff41..9e22e023753f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -46,22 +46,28 @@ class XBreakpointItem extends BreakpointItem { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - setupGenericRenderer(renderer); + setupGenericRenderer(renderer, false); } @Override public void setupRenderer(ColoredTreeCellRenderer renderer) { - setupGenericRenderer(renderer); + setupGenericRenderer(renderer, false); } - protected void setupGenericRenderer(SimpleColoredComponent renderer) { - //renderer.setIcon(getIcon()); + protected void setupGenericRenderer(SimpleColoredComponent renderer, boolean plainView) { + if (plainView) { + renderer.setIcon(getIcon()); + } final SimpleTextAttributes attributes = myBreakpoint.isEnabled() ? SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES; - renderer.append(XBreakpointUtil.getShortText(myBreakpoint), attributes); + renderer.append(getDisplayText(), attributes); } - private Icon getIcon() { + public String getDisplayText() { + return XBreakpointUtil.getShortText(myBreakpoint); + } + + public Icon getIcon() { return ((XBreakpointBase)myBreakpoint).getIcon(); } @@ -75,21 +81,22 @@ class XBreakpointItem extends BreakpointItem { return ((XBreakpointBase)myBreakpoint).getType().getDisplayText(myBreakpoint); } - @Override - public void updateDetailView(DetailView panel) { + public void doUpdateDetailView(DetailView panel) { Project project = ((XBreakpointBase)myBreakpoint).getProject(); + XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); + if (sourcePosition != null) { + if (!showInEditor(panel, sourcePosition.getFile(), sourcePosition.getLine())) { + return; + } + } else { + panel.clearEditor(); + } + XLightBreakpointPropertiesPanel> propertiesPanel = new XLightBreakpointPropertiesPanel>(project, getManager(), myBreakpoint, true); propertiesPanel.loadProperties(); panel.setDetailPanel(propertiesPanel.getMainPanel()); - - XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); - if (sourcePosition != null) { - showInEditor(panel, sourcePosition.getFile(), sourcePosition.getLine()); - } else { - panel.clearEditor(); - } } private XBreakpointManagerImpl getManager() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 748c2789f3f2..8d4bb612ce6c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -22,6 +22,7 @@ import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupListener; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.xdebugger.impl.DebuggerSupport; +import com.intellij.xdebugger.impl.breakpoints.ui.tree.BreakpointMasterDetailPopupBuilder; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -31,22 +32,26 @@ import java.util.List; public class BreakpointsMasterDetailPopupFactory { - private final List myBreakpointPanelProviders; private Project myProject; private Balloon myBalloonToHide; public BreakpointsMasterDetailPopupFactory(Project project) { myProject = project; - myBreakpointPanelProviders = new ArrayList(); + collectPanelProviders(); + } + + public static List collectPanelProviders() { + List panelProviders = new ArrayList(); for (DebuggerSupport debuggerSupport : DebuggerSupport.getDebuggerSupports()) { - myBreakpointPanelProviders.add(debuggerSupport.getBreakpointPanelProvider()); + panelProviders.add(debuggerSupport.getBreakpointPanelProvider()); } - Collections.sort(myBreakpointPanelProviders, new Comparator() { + Collections.sort(panelProviders, new Comparator() { @Override public int compare(BreakpointPanelProvider o1, BreakpointPanelProvider o2) { return o2.getPriority() - o1.getPriority(); } }); + return panelProviders; } public void setBalloonToHide(Balloon balloonToHide) { @@ -60,7 +65,7 @@ public class BreakpointsMasterDetailPopupFactory { public JBPopup createPopup(@Nullable Object initialBreakpoint) { BreakpointMasterDetailPopupBuilder builder = new BreakpointMasterDetailPopupBuilder(myProject); builder.setInitialBreakpoint(initialBreakpoint); - builder.setBreakpointsPanelProviders(myBreakpointPanelProviders); + builder.setBreakpointsPanelProviders(collectPanelProviders()); final JBPopup popup = builder.createPopup(); popup.addListener(new JBPopupListener() { @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemNode.java new file mode 100644 index 000000000000..4393ce9389d4 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemNode.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2012 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.ui.tree; + +import com.intellij.ui.CheckedTreeNode; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; + +class BreakpointItemNode extends CheckedTreeNode { + private final BreakpointItem myBreakpoint; + + BreakpointItemNode(final BreakpointItem breakpoint) { + super(breakpoint); + myBreakpoint = breakpoint; + setChecked(breakpoint.isEnabled()); + } + + public BreakpointItem getBreakpointItem() { + return myBreakpoint; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItemsTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java similarity index 74% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItemsTree.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java index 13fe05927c62..b94ec8b72ed8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItemsTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointItemsTreeController.java @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.impl.breakpoints.ui; +package com.intellij.xdebugger.impl.breakpoints.ui.tree; import com.intellij.ide.util.treeView.TreeState; import com.intellij.openapi.util.MultiValuesMap; -import com.intellij.ui.CheckboxTree; import com.intellij.ui.CheckedTreeNode; -import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XBreakpointManager; @@ -39,7 +37,7 @@ import java.util.*; /** * @author nik, zajac */ -public class BreakpointItemsTree extends CheckboxTree { +public class BreakpointItemsTreeController implements BreakpointsCheckboxTree.Delegate { //private final TreeNodeComparator myComparator; private final CheckedTreeNode myRoot; private final Map myNodes = new HashMap(); @@ -50,14 +48,20 @@ public class BreakpointItemsTree extends CheckboxTree { private final MultiValuesMap myGroups = new MultiValuesMap(); - private BreakpointItemsTree(final CheckedTreeNode root, - Collection groupingRules) { - super(new BreakpointsTreeCellRenderer(), root); - myRoot = root; + private JTree myTreeView; + + public BreakpointItemsTreeController(Collection groupingRules) { + myRoot = new CheckedTreeNode("root"); //myComparator = new TreeNodeComparator(type, breakpointManager); setGroupingRulesInternal(groupingRules); + } - getEmptyText().setText("No Breakpoints"); + public void setTreeView(JTree treeView) { + myTreeView = treeView; + if (treeView instanceof BreakpointsCheckboxTree) { + ((BreakpointsCheckboxTree)treeView).setDelegate(this); + } + myTreeView.setShowsRootHandles(!myGroupingRules.isEmpty()); } public void setDelegate(BreakpointItemsTreeDelegate delegate) { @@ -66,15 +70,10 @@ public class BreakpointItemsTree extends CheckboxTree { private void setGroupingRulesInternal(final Collection groupingRules) { myGroupingRules = new ArrayList(groupingRules); - setShowsRootHandles(!groupingRules.isEmpty()); - } - - public static BreakpointItemsTree createTree(final Collection groupingRules) { - return new BreakpointItemsTree(new CheckedTreeNode("root"), groupingRules); } public void buildTree(@NotNull Collection breakpoints) { - final TreeState state = TreeState.createOn(this, myRoot); + final TreeState state = TreeState.createOn(myTreeView, myRoot); myRoot.removeAllChildren(); myNodes.clear(); myGroupNodes.clear(); @@ -86,9 +85,9 @@ public class BreakpointItemsTree extends CheckboxTree { myNodes.put(breakpoint, node); } //TreeUtil.sort(myRoot, myComparator); - ((DefaultTreeModel)getModel()).nodeStructureChanged(myRoot); - state.applyTo(this, myRoot); - TreeUtil.expandAll(this); + ((DefaultTreeModel)(myTreeView.getModel())).nodeStructureChanged(myRoot); + state.applyTo(myTreeView, myRoot); + TreeUtil.expandAll(myTreeView); } @@ -146,24 +145,28 @@ public class BreakpointItemsTree extends CheckboxTree { } @Override - protected void onDoubleClick(CheckedTreeNode node) { + public void didSelectNode(CheckedTreeNode node) { if (node instanceof BreakpointItemNode) { myDelegate.execute(((BreakpointItemNode)node).getBreakpointItem()); } } @Override - protected void onNodeStateChanged(final CheckedTreeNode node) { + public void nodeStateChanged(CheckedTreeNode node) { if (node instanceof BreakpointItemNode) { ((BreakpointItemNode)node).getBreakpointItem().setEnabled(node.isChecked()); } } public void setGroupingRules(Collection groupingRules) { - List selectedBreakpoints = getSelectedBreakpoints(); - List allBreakpoints = new ArrayList(myNodes.keySet()); - setGroupingRulesInternal(groupingRules); + rebuildTree(new ArrayList(myNodes.keySet())); + } + + public void rebuildTree(Collection items) { + List selectedBreakpoints = getSelectedBreakpoints(); + Collection allBreakpoints = items; + buildTree(allBreakpoints); if (selectedBreakpoints.size() > 0) { @@ -173,7 +176,7 @@ public class BreakpointItemsTree extends CheckboxTree { public List getSelectedBreakpoints() { final ArrayList list = new ArrayList(); - TreePath[] selectionPaths = getSelectionPaths(); + TreePath[] selectionPaths = myTreeView.getSelectionPaths(); if (selectionPaths == null || selectionPaths.length == 0) return list; for (TreePath selectionPath : selectionPaths) { @@ -193,58 +196,12 @@ public class BreakpointItemsTree extends CheckboxTree { public void selectBreakpointItem(final BreakpointItem breakpoint) { BreakpointItemNode node = myNodes.get(breakpoint); if (node != null) { - TreeUtil.selectNode(this, node); + TreeUtil.selectNode(myTreeView, node); } } - private static class BreakpointsTreeCellRenderer extends CheckboxTreeCellRenderer { - @Override - public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { - if (value instanceof BreakpointItemNode) { - BreakpointItemNode node = (BreakpointItemNode)value; - BreakpointItem breakpoint = node.getBreakpointItem(); - breakpoint.setupRenderer(getTextRenderer()); - } - else if (value instanceof BreakpointsGroupNode) { - XBreakpointGroup group = ((BreakpointsGroupNode)value).getGroup(); - getTextRenderer().setIcon(group.getIcon(expanded)); - getTextRenderer().append(group.getName(), SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES); - } - } - } - - private static class BreakpointsGroupNode extends CheckedTreeNode { - private final G myGroup; - private final int myLevel; - - private BreakpointsGroupNode(G group, int level) { - super(group); - myLevel = level; - setChecked(false); - myGroup = group; - } - - public G getGroup() { - return myGroup; - } - - public int getLevel() { - return myLevel; - } - } - - private static class BreakpointItemNode extends CheckedTreeNode { - private final BreakpointItem myBreakpoint; - - private BreakpointItemNode(final BreakpointItem breakpoint) { - super(breakpoint); - myBreakpoint = breakpoint; - setChecked(breakpoint.isEnabled()); - } - - public BreakpointItem getBreakpointItem() { - return myBreakpoint; - } + public CheckedTreeNode getRoot() { + return myRoot; } private static class TreeNodeComparator> implements Comparator { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointMasterDetailPopupBuilder.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointMasterDetailPopupBuilder.java similarity index 58% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointMasterDetailPopupBuilder.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointMasterDetailPopupBuilder.java index fce09fb83953..1514342a3546 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointMasterDetailPopupBuilder.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointMasterDetailPopupBuilder.java @@ -13,53 +13,94 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.impl.breakpoints.ui; +package com.intellij.xdebugger.impl.breakpoints.ui.tree; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.ex.CheckboxAction; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; -import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl; -import com.intellij.openapi.editor.markup.EffectType; -import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.JBPopupListener; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.util.IconUtil; import com.intellij.util.PlatformIcons; import com.intellij.util.containers.HashSet; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; -import com.intellij.xdebugger.ui.DebuggerColors; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; +import java.util.*; public class BreakpointMasterDetailPopupBuilder { private Project myProject; private MasterDetailPopupBuilder myPopupBuilder; - private Collection myBreakpointsPanelProviders; - private BreakpointItemsTree myTree; + private Collection myBreakpointsPanelProviders = Collections.emptyList(); + private BreakpointItemsTreeController myTreeController; private final List myRulesAvailable = new ArrayList(); private final Set myRulesEnabled = new HashSet(); @Nullable private Object myInitialBreakpoint; + @Nullable private BreakpointChosenCallback myCallback = null; + + private boolean myAddDetailViewToEast = true; + + private DetailView myDetailView; + + private boolean myIsViewer; + + private boolean myPlainView = false; + + public boolean isPlainView() { + return myPlainView; + } + + public void setPlainView(boolean plainView) { + myPlainView = plainView; + } + + public Collection getBreakpointItems() { + return myBreakpointItems; + } + + public void setBreakpointItems(Collection breakpointItems) { + myBreakpointItems = breakpointItems; + } + + private Collection myBreakpointItems = new ArrayList(); + + public void setDetailView(DetailView detailView) { + myDetailView = detailView; + } + + public void setAddDetailViewToEast(boolean addDetailViewToEast) { + myAddDetailViewToEast = addDetailViewToEast; + } + + public void setCallback(BreakpointChosenCallback callback) { + myCallback = callback; + } + + public void setIsViewer(boolean isViewer) { + myIsViewer = isViewer; + } + + public interface BreakpointChosenCallback { + void breakpointChosen(Project project, BreakpointItem breakpointItem, JBPopup popup); + } + public void setInitialBreakpoint(@Nullable Object initialBreakpoint) { myInitialBreakpoint = initialBreakpoint; } @@ -67,34 +108,50 @@ public class BreakpointMasterDetailPopupBuilder { public BreakpointMasterDetailPopupBuilder(Project project) { myProject = project; } - public JBPopup createPopup() { myPopupBuilder = new MasterDetailPopupBuilder(myProject); + if (myDetailView != null) { + myPopupBuilder.setDetailView(myDetailView); + } + myPopupBuilder.setAddDetailViewToEast(myAddDetailViewToEast); + for (BreakpointPanelProvider provider : myBreakpointsPanelProviders) { provider.createBreakpointsGroupingRules(myRulesAvailable); } - for (XBreakpointGroupingRule rule : myRulesAvailable) { - if (rule.isAlwaysEnabled()) { - myRulesEnabled.add(rule); + if (!myIsViewer) { + for (XBreakpointGroupingRule rule : myRulesAvailable) { + if (rule.isAlwaysEnabled()) { + myRulesEnabled.add(rule); + } } } DefaultActionGroup actions = createActions(); - myTree = BreakpointItemsTree.createTree(getEnabledRulesList()); + myTreeController = new BreakpointItemsTreeController(getEnabledRulesList()); - final ArrayList breakpoints = collectItems(); - myTree.buildTree(breakpoints); + JTree tree = myIsViewer ? new BreakpointsSimpleTree(myTreeController) : new BreakpointsCheckboxTree(myTreeController); + + if (myPlainView) { + tree.putClientProperty("plainView", Boolean.TRUE); + } + + myTreeController.setTreeView(tree); + + collectItems(); + + myTreeController.buildTree(myBreakpointItems); final BreakpointPanelProvider.BreakpointsListener listener = new BreakpointPanelProvider.BreakpointsListener() { @Override public void breakpointsChanged() { - myTree.buildTree(collectItems()); + collectItems(); + myTreeController.rebuildTree(myBreakpointItems); } }; @@ -102,41 +159,55 @@ public class BreakpointMasterDetailPopupBuilder { provider.addListener(listener, myProject); } + final MasterDetailPopupBuilder.Delegate delegate = new MasterDetailPopupBuilder.Delegate() { + @Nullable + @Override + public String getTitle() { + return myIsViewer ? null : "Breakpoints"; + } + + @Override + public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public JComponent createAccessoryView(Project project) { + return new JCheckBox(); + } + + @Override + public Object[] getSelectedItemsInTree() { + final List res = myTreeController.getSelectedBreakpoints(); + return res.toArray(new Object[res.size()]); + } + + @Override + public void itemChosen(ItemWrapper item, Project project, JBPopup popup) { + if (!(item instanceof BreakpointItem)) { + return; + } + if (myCallback != null){ + myCallback.breakpointChosen(project, (BreakpointItem)item, popup); + } + } + }; + final JBPopup popup = myPopupBuilder. setActionsGroup(actions). - setTree(myTree). - setDelegate(new MasterDetailPopupBuilder.Delegate() { - @Override - public String getTitle() { - return "Breakpoints"; - } + setTree(tree). + setDelegate(delegate). + setCloseOnEnter(false).createMasterDetailPopup(); - @Override - public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { - //To change body of implemented methods use File | Settings | File Templates. - } + tree.setBorder(IdeBorderFactory.createBorder()); - public JComponent createAccessoryView(Project project) { - return new JCheckBox(); - } - - @Override - public Object[] getSelectedItemsInTree() { - final List res = myTree.getSelectedBreakpoints(); - return res.toArray(new Object[res.size()]); - } - }).setCloseOnEnter(false).createMasterDetailPopup(); - - myTree.setBorder(IdeBorderFactory.createBorder()); - - myTree.setDelegate(new BreakpointItemsTree.BreakpointItemsTreeDelegate() { + myTreeController.setDelegate(new BreakpointItemsTreeController.BreakpointItemsTreeDelegate() { @Override public void execute(BreakpointItem item) { - item.execute(myProject, popup); + delegate.itemChosen(item, myProject, popup); } }); - initSelection(breakpoints); + initSelection(myBreakpointItems); popup.addListener(new JBPopupListener() { @Override @@ -155,31 +226,26 @@ public class BreakpointMasterDetailPopupBuilder { return popup; } - void initSelection(ArrayList breakpoints) { + void initSelection(Collection breakpoints) { boolean found = false; for (BreakpointItem breakpoint : breakpoints) { if (breakpoint.getBreakpoint() == myInitialBreakpoint) { - myTree.selectBreakpointItem(breakpoint); + myTreeController.selectBreakpointItem(breakpoint); found = true; break; } } if (!found && !breakpoints.isEmpty()) { - myTree.selectBreakpointItem(breakpoints.get(0)); + myTreeController.selectBreakpointItem(breakpoints.iterator().next()); } } - EditorColorsScheme createScheme() { - final EditorColorsScheme scheme = - new EditorColorsSchemeImpl(EditorColorsManager.getInstance().getGlobalScheme(), DefaultColorSchemesManager.getInstance()); - scheme.setName("abc"); - scheme - .setAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES, new TextAttributes(Color.black, Color.CYAN, null, EffectType.BOXED, Font.BOLD)); - return scheme; - } - + @Nullable DefaultActionGroup createActions() { + if (myIsViewer) { + return null; + } DefaultActionGroup actions = new DefaultActionGroup(); final DefaultActionGroup breakpointTypes = new DefaultActionGroup(); for (BreakpointPanelProvider provider : myBreakpointsPanelProviders) { @@ -215,15 +281,16 @@ public class BreakpointMasterDetailPopupBuilder { return actions; } - ArrayList collectItems() { - ArrayList items = new ArrayList(); - for (BreakpointPanelProvider panelProvider : myBreakpointsPanelProviders) { - panelProvider.provideBreakpointItems(myProject, items); + void collectItems() { + if (!myBreakpointsPanelProviders.isEmpty()) { + myBreakpointItems.clear(); + for (BreakpointPanelProvider panelProvider : myBreakpointsPanelProviders) { + panelProvider.provideBreakpointItems(myProject, myBreakpointItems); + } } - return items; } - public void setBreakpointsPanelProviders(Collection breakpointsPanelProviders) { + public void setBreakpointsPanelProviders(@NotNull Collection breakpointsPanelProviders) { myBreakpointsPanelProviders = breakpointsPanelProviders; } @@ -249,7 +316,7 @@ public class BreakpointMasterDetailPopupBuilder { else { myRulesEnabled.remove(myRule); } - myTree.setGroupingRules(getEnabledRulesList()); + myTreeController.setGroupingRules(getEnabledRulesList()); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsCheckboxTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsCheckboxTree.java new file mode 100644 index 000000000000..2194b662d719 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsCheckboxTree.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2012 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.ui.tree; + +import com.intellij.ui.CheckboxTree; +import com.intellij.ui.CheckedTreeNode; + +public class BreakpointsCheckboxTree extends CheckboxTree { + + + @Override + protected void onDoubleClick(CheckedTreeNode node) { + super.onDoubleClick(node); + if (myDelegate != null) { + myDelegate.didSelectNode(node); + } + } + + @Override + protected void onNodeStateChanged(CheckedTreeNode node) { + super.onNodeStateChanged(node); + if (myDelegate != null) { + myDelegate.nodeStateChanged(node); + } + } + + interface Delegate { + void didSelectNode(CheckedTreeNode node); + + void nodeStateChanged(CheckedTreeNode node); + } + + public void setDelegate(Delegate delegate) { + myDelegate = delegate; + } + + private Delegate myDelegate = null; + + public BreakpointsCheckboxTree(BreakpointItemsTreeController model) { + super(new BreakpointsTreeCellRenderer.BreakpointsCheckboxTreeCellRenderer(), model.getRoot()); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsGroupNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsGroupNode.java new file mode 100644 index 000000000000..d6868352d8a8 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsGroupNode.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2012 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.ui.tree; + +import com.intellij.ui.CheckedTreeNode; +import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup; + +class BreakpointsGroupNode extends CheckedTreeNode { + private final G myGroup; + private final int myLevel; + + BreakpointsGroupNode(G group, int level) { + super(group); + myLevel = level; + setChecked(false); + myGroup = group; + } + + public G getGroup() { + return myGroup; + } + + public int getLevel() { + return myLevel; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsSimpleTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsSimpleTree.java new file mode 100644 index 000000000000..b7e1c70d900c --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsSimpleTree.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2012 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.ui.tree; + +import com.intellij.ui.treeStructure.Tree; + +public class BreakpointsSimpleTree extends Tree { + public BreakpointsSimpleTree(BreakpointItemsTreeController controller) { + super(controller.getRoot()); + setCellRenderer(new BreakpointsTreeCellRenderer.BreakpointsSimpleTreeCellRenderer()); + setRootVisible(false); + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsTreeCellRenderer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsTreeCellRenderer.java new file mode 100644 index 000000000000..0878e291903d --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/tree/BreakpointsTreeCellRenderer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2012 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.ui.tree; + +import com.intellij.ui.CheckboxTree; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup; + +import javax.swing.*; + +class BreakpointsTreeCellRenderer { + private static void customizeRenderer(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus, + ColoredTreeCellRenderer renderer) { + if (value instanceof BreakpointItemNode) { + BreakpointItemNode node = (BreakpointItemNode)value; + BreakpointItem breakpoint = node.getBreakpointItem(); + breakpoint.setupRenderer(renderer); + } + else if (value instanceof BreakpointsGroupNode) { + XBreakpointGroup group = ((BreakpointsGroupNode)value).getGroup(); + renderer.setIcon(group.getIcon(expanded)); + renderer.append(group.getName(), SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES); + } + } + + public static class BreakpointsCheckboxTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer { + @Override + public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + BreakpointsTreeCellRenderer.customizeRenderer(tree, value, selected, expanded, leaf, row, hasFocus, getTextRenderer()); + } + } + + public static class BreakpointsSimpleTreeCellRenderer extends ColoredTreeCellRenderer { + + @Override + public void customizeCellRenderer(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + BreakpointsTreeCellRenderer.customizeRenderer(tree, value, selected, expanded, leaf, row, hasFocus, this); + } + } +} diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskCombo.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskCombo.java index 8b7135769d4c..300981ef56ea 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskCombo.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskCombo.java @@ -21,7 +21,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; @@ -65,7 +65,7 @@ public class SwitchTaskCombo extends ComboBoxAction implements DumbAware { } @Override - protected ListPopup createPopup(Runnable onDispose) { + protected JBPopup createPopup(Runnable onDispose) { return SwitchTaskAction.createPopup(DataManager.getInstance().getDataContext(this), onDispose, false); } }; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java index 90cc87f7926f..6528a310515a 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/AbstractComboBoxAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.util.PlatformIcons; @@ -85,7 +86,7 @@ public abstract class AbstractComboBoxAction extends ComboBoxAction { if (myShowDisabledActions) { return new ComboBoxButton(presentation) { @Override - protected ListPopup createPopup(Runnable onDispose) { + protected JBPopup createPopup(Runnable onDispose) { ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup( null, createPopupActionGroup(this), getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true, onDispose, getMaxRows());