summaryrefslogtreecommitdiff
path: root/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java')
-rw-r--r--java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java402
1 files changed, 402 insertions, 0 deletions
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
new file mode 100644
index 000000000000..2afcf0fd339f
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointFiltersPanel.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.java.debugger.breakpoints;
+
+import com.intellij.debugger.InstanceFilter;
+import com.intellij.debugger.ui.breakpoints.EditClassFiltersDialog;
+import com.intellij.debugger.ui.breakpoints.EditInstanceFiltersDialog;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.ui.FieldPanel;
+import com.intellij.ui.MultiLineTooltipUI;
+import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.breakpoints.XBreakpoint;
+import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author egor
+ */
+public class JavaBreakpointFiltersPanel<T extends JavaBreakpointProperties, B extends XBreakpoint<T>> extends XBreakpointCustomPropertiesPanel<B> {
+ private JPanel myConditionsPanel;
+ private JPanel myInstanceFiltersPanel;
+ private JCheckBox myInstanceFiltersCheckBox;
+ private JPanel myInstanceFiltersFieldPanel;
+ private JPanel myClassFiltersPanel;
+ private JCheckBox myClassFiltersCheckBox;
+ private JPanel myClassFiltersFieldPanel;
+ private JPanel myPassCountPanel;
+ private JCheckBox myPassCountCheckbox;
+ private JTextField myPassCountField;
+
+ private final FieldPanel myInstanceFiltersField;
+ private final FieldPanel myClassFiltersField;
+
+ private ClassFilter[] myClassFilters = ClassFilter.EMPTY_ARRAY;
+ private ClassFilter[] myClassExclusionFilters = ClassFilter.EMPTY_ARRAY;
+ private InstanceFilter[] myInstanceFilters = InstanceFilter.EMPTY_ARRAY;
+ protected final Project myProject;
+
+ private PsiClass myBreakpointPsiClass;
+
+ public JavaBreakpointFiltersPanel(Project project) {
+ myProject = project;
+ myInstanceFiltersField = new FieldPanel(new MyTextField(), "", null,
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reloadInstanceFilters();
+ EditInstanceFiltersDialog _dialog = new EditInstanceFiltersDialog(myProject);
+ _dialog.setFilters(myInstanceFilters);
+ _dialog.show();
+ if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
+ myInstanceFilters = _dialog.getFilters();
+ updateInstanceFilterEditor(true);
+ }
+ }
+ },
+ null
+ );
+
+ myClassFiltersField = new FieldPanel(new MyTextField(), "", null,
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reloadClassFilters();
+
+ com.intellij.ide.util.ClassFilter classFilter = createClassConditionFilter();
+
+ EditClassFiltersDialog _dialog = new EditClassFiltersDialog(myProject, classFilter);
+ _dialog.setFilters(myClassFilters, myClassExclusionFilters);
+ _dialog.show();
+ if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
+ myClassFilters = _dialog.getFilters();
+ myClassExclusionFilters = _dialog.getExclusionFilters();
+ updateClassFilterEditor(true);
+ }
+ }
+ },
+ null
+ );
+
+ ActionListener updateListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateCheckboxes();
+ }
+ };
+
+ myPassCountCheckbox.addActionListener(updateListener);
+ myInstanceFiltersCheckBox.addActionListener(updateListener);
+ myClassFiltersCheckBox.addActionListener(updateListener);
+
+ ToolTipManager.sharedInstance().registerComponent(myClassFiltersField.getTextField());
+ ToolTipManager.sharedInstance().registerComponent(myInstanceFiltersField.getTextField());
+
+ insert(myInstanceFiltersFieldPanel, myInstanceFiltersField);
+ insert(myClassFiltersFieldPanel, myClassFiltersField);
+
+ DebuggerUIUtil.focusEditorOnCheck(myPassCountCheckbox, myPassCountField);
+ DebuggerUIUtil.focusEditorOnCheck(myInstanceFiltersCheckBox, myInstanceFiltersField.getTextField());
+ DebuggerUIUtil.focusEditorOnCheck(myClassFiltersCheckBox, myClassFiltersField.getTextField());
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myConditionsPanel;
+ }
+
+ @Override
+ public boolean isVisibleOnPopup(@NotNull B breakpoint) {
+ JavaBreakpointProperties properties = breakpoint.getProperties();
+ if (properties != null) {
+ return properties.COUNT_FILTER_ENABLED || properties.CLASS_FILTERS_ENABLED || properties.INSTANCE_FILTERS_ENABLED;
+ }
+ return false;
+ }
+
+ @Override
+ public void saveTo(@NotNull B breakpoint) {
+ JavaBreakpointProperties properties = breakpoint.getProperties();
+ if (properties == null) {
+ return;
+ }
+
+ try {
+ String text = myPassCountField.getText().trim();
+ properties.COUNT_FILTER = !text.isEmpty() ? Integer.parseInt(text) : 0;
+ if (properties.COUNT_FILTER < 0) {
+ properties.COUNT_FILTER = 0;
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ properties.COUNT_FILTER_ENABLED = properties.COUNT_FILTER > 0 && myPassCountCheckbox.isSelected();
+ reloadInstanceFilters();
+ reloadClassFilters();
+ updateInstanceFilterEditor(true);
+ updateClassFilterEditor(true);
+
+ properties.INSTANCE_FILTERS_ENABLED = myInstanceFiltersField.getText().length() > 0 && myInstanceFiltersCheckBox.isSelected();
+ properties.CLASS_FILTERS_ENABLED = myClassFiltersField.getText().length() > 0 && myClassFiltersCheckBox.isSelected();
+ properties.setClassFilters(myClassFilters);
+ properties.setClassExclusionFilters(myClassExclusionFilters);
+ properties.setInstanceFilters(myInstanceFilters);
+ }
+
+ private static void insert(JPanel panel, JComponent component) {
+ panel.setLayout(new BorderLayout());
+ panel.add(component, BorderLayout.CENTER);
+ }
+
+ @Override
+ public void loadFrom(@NotNull B breakpoint) {
+ JavaBreakpointProperties properties = breakpoint.getProperties();
+ if (properties != null) {
+ if (properties.COUNT_FILTER > 0) {
+ myPassCountField.setText(Integer.toString(properties.COUNT_FILTER));
+ }
+ else {
+ myPassCountField.setText("");
+ }
+
+ myPassCountCheckbox.setSelected(properties.COUNT_FILTER_ENABLED);
+
+ myInstanceFiltersCheckBox.setSelected(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFiltersField.setEnabled(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFiltersField.getTextField().setEditable(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFilters = properties.getInstanceFilters();
+ updateInstanceFilterEditor(true);
+
+ myClassFiltersCheckBox.setSelected(properties.CLASS_FILTERS_ENABLED);
+ myClassFiltersField.setEnabled(properties.CLASS_FILTERS_ENABLED);
+ myClassFiltersField.getTextField().setEditable(properties.CLASS_FILTERS_ENABLED);
+ myClassFilters = properties.getClassFilters();
+ myClassExclusionFilters = properties.getClassExclusionFilters();
+ updateClassFilterEditor(true);
+
+ XSourcePosition position = breakpoint.getSourcePosition();
+ // TODO: need to calculate psi class
+ //myBreakpointPsiClass = breakpoint.getPsiClass();
+ }
+ updateCheckboxes();
+ }
+
+ private void updateInstanceFilterEditor(boolean updateText) {
+ List<String> filters = new ArrayList<String>();
+ for (InstanceFilter instanceFilter : myInstanceFilters) {
+ if (instanceFilter.isEnabled()) {
+ filters.add(Long.toString(instanceFilter.getId()));
+ }
+ }
+ if (updateText) {
+ myInstanceFiltersField.setText(StringUtil.join(filters, " "));
+ }
+
+ String tipText = concatWithEx(filters, " ", (int)Math.sqrt(myInstanceFilters.length) + 1, "\n");
+ myInstanceFiltersField.getTextField().setToolTipText(tipText);
+ }
+
+ private class MyTextField extends JTextField {
+ public MyTextField() {
+ }
+
+ @Override
+ public String getToolTipText(MouseEvent event) {
+ reloadClassFilters();
+ updateClassFilterEditor(false);
+ reloadInstanceFilters();
+ updateInstanceFilterEditor(false);
+ String toolTipText = super.getToolTipText(event);
+ return getToolTipText().length() == 0 ? null : toolTipText;
+ }
+
+ @Override
+ public JToolTip createToolTip() {
+ JToolTip toolTip = new JToolTip(){{
+ setUI(new MultiLineTooltipUI());
+ }};
+ toolTip.setComponent(this);
+ return toolTip;
+ }
+ }
+
+ private void reloadClassFilters() {
+ String filtersText = myClassFiltersField.getText();
+
+ ArrayList<ClassFilter> classFilters = new ArrayList<ClassFilter>();
+ ArrayList<ClassFilter> exclusionFilters = new ArrayList<ClassFilter>();
+ int startFilter = -1;
+ for(int i = 0; i <= filtersText.length(); i++) {
+ if(i < filtersText.length() && !Character.isWhitespace(filtersText.charAt(i))){
+ if(startFilter == -1) {
+ startFilter = i;
+ }
+ }
+ else {
+ if(startFilter >=0) {
+ if(filtersText.charAt(startFilter) == '-') {
+ exclusionFilters.add(new ClassFilter(filtersText.substring(startFilter + 1, i)));
+ }
+ else {
+ classFilters.add(new ClassFilter(filtersText.substring(startFilter, i)));
+ }
+ startFilter = -1;
+ }
+ }
+ }
+ for (ClassFilter classFilter : myClassFilters) {
+ if (!classFilter.isEnabled()) {
+ classFilters.add(classFilter);
+ }
+ }
+ for (ClassFilter classFilter : myClassExclusionFilters) {
+ if (!classFilter.isEnabled()) {
+ exclusionFilters.add(classFilter);
+ }
+ }
+ myClassFilters = classFilters .toArray(new ClassFilter[classFilters .size()]);
+ myClassExclusionFilters = exclusionFilters.toArray(new ClassFilter[exclusionFilters.size()]);
+ }
+
+ private void reloadInstanceFilters() {
+ String filtersText = myInstanceFiltersField.getText();
+
+ ArrayList<InstanceFilter> idxs = new ArrayList<InstanceFilter>();
+ int startNumber = -1;
+ for(int i = 0; i <= filtersText.length(); i++) {
+ if(i < filtersText.length() && Character.isDigit(filtersText.charAt(i))) {
+ if(startNumber == -1) {
+ startNumber = i;
+ }
+ }
+ else {
+ if(startNumber >=0) {
+ idxs.add(InstanceFilter.create(filtersText.substring(startNumber, i)));
+ startNumber = -1;
+ }
+ }
+ }
+ for (InstanceFilter instanceFilter : myInstanceFilters) {
+ if (!instanceFilter.isEnabled()) {
+ idxs.add(instanceFilter);
+ }
+ }
+ myInstanceFilters = idxs.toArray(new InstanceFilter[idxs.size()]);
+ }
+
+ private void updateClassFilterEditor(boolean updateText) {
+ List<String> filters = new ArrayList<String>();
+ for (ClassFilter classFilter : myClassFilters) {
+ if (classFilter.isEnabled()) {
+ filters.add(classFilter.getPattern());
+ }
+ }
+ List<String> excludeFilters = new ArrayList<String>();
+ for (ClassFilter classFilter : myClassExclusionFilters) {
+ if (classFilter.isEnabled()) {
+ excludeFilters.add("-" + classFilter.getPattern());
+ }
+ }
+ if (updateText) {
+ String editorText = StringUtil.join(filters, " ");
+ if(!filters.isEmpty()) {
+ editorText += " ";
+ }
+ editorText += StringUtil.join(excludeFilters, " ");
+ myClassFiltersField.setText(editorText);
+ }
+
+ int width = (int)Math.sqrt(myClassExclusionFilters.length + myClassFilters.length) + 1;
+ String tipText = concatWithEx(filters, " ", width, "\n");
+ if(!filters.isEmpty()) {
+ tipText += "\n";
+ }
+ tipText += concatWithEx(excludeFilters, " ", width, "\n");
+ myClassFiltersField.getTextField().setToolTipText(tipText);
+ }
+
+ private static String concatWithEx(List<String> s, String concator, int N, String NthConcator) {
+ String result = "";
+ int i = 1;
+ for (Iterator iterator = s.iterator(); iterator.hasNext(); i++) {
+ String str = (String) iterator.next();
+ result += str;
+ if(iterator.hasNext()){
+ if(i % N == 0){
+ result += NthConcator;
+ }
+ else {
+ result += concator;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected com.intellij.ide.util.ClassFilter createClassConditionFilter() {
+ com.intellij.ide.util.ClassFilter classFilter;
+ if(myBreakpointPsiClass != null) {
+ classFilter = new com.intellij.ide.util.ClassFilter() {
+ @Override
+ public boolean isAccepted(PsiClass aClass) {
+ return myBreakpointPsiClass == aClass || aClass.isInheritor(myBreakpointPsiClass, true);
+ }
+ };
+ }
+ else {
+ classFilter = null;
+ }
+ return classFilter;
+ }
+
+ protected void updateCheckboxes() {
+ boolean passCountApplicable = true;
+ if (myInstanceFiltersCheckBox.isSelected() || myClassFiltersCheckBox.isSelected()) {
+ passCountApplicable = false;
+ }
+ myPassCountCheckbox.setEnabled(passCountApplicable);
+
+ final boolean passCountSelected = myPassCountCheckbox.isSelected();
+ myInstanceFiltersCheckBox.setEnabled(!passCountSelected);
+ myClassFiltersCheckBox.setEnabled(!passCountSelected);
+
+ myPassCountField.setEditable(myPassCountCheckbox.isSelected());
+ myPassCountField.setEnabled (myPassCountCheckbox.isSelected());
+
+ myInstanceFiltersField.setEnabled(myInstanceFiltersCheckBox.isSelected());
+ myInstanceFiltersField.getTextField().setEditable(myInstanceFiltersCheckBox.isSelected());
+
+ myClassFiltersField.setEnabled(myClassFiltersCheckBox.isSelected());
+ myClassFiltersField.getTextField().setEditable(myClassFiltersCheckBox.isSelected());
+ }
+}