<commit_before>/*
 * Copyright 2000-2009 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.usages.impl;

import com.intellij.find.FindManager;
import com.intellij.icons.AllIcons;
import com.intellij.ide.*;
import com.intellij.ide.actions.CloseTabToolbarAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.*;
import com.intellij.ui.content.Content;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usageView.UsageViewManager;
import com.intellij.usages.*;
import com.intellij.usages.rules.*;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author max
 */
public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTrackerListener {
  @NonNls public static final String SHOW_RECENT_FIND_USAGES_ACTION_ID = "UsageView.ShowRecentFindUsages";
  private static final boolean EXPAND_ALL = Registry.is("find.usage.expand.all");

  private final UsageNodeTreeBuilder myBuilder;
  private final MyPanel myRootPanel;
  private final JTree myTree;
  private Content myContent;

  private final UsageViewPresentation myPresentation;
  private final UsageTarget[] myTargets;
  private final Factory<UsageSearcher> myUsageSearcherFactory;
  private final Project myProject;

  private boolean mySearchInProgress = true;
  private ExporterToTextFile myTextFileExporter;
  private final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);

  private final UsageModelTracker myModelTracker;
  private final Map<Usage, UsageNode> myUsageNodes = new ConcurrentHashMap<Usage, UsageNode>();
  public static final UsageNode NULL_NODE = new UsageNode(NullUsage.INSTANCE, new UsageViewTreeModelBuilder(new UsageViewPresentation(), UsageTarget.EMPTY_ARRAY));
  private final ButtonPanel myButtonPanel = new ButtonPanel();
  private volatile boolean isDisposed;
  private volatile boolean myChangesDetected = false;
  static final Comparator<Usage> USAGE_COMPARATOR = new Comparator<Usage>() {
    @Override
    public int compare(final Usage o1, final Usage o2) {
      if (o1 == NULL_NODE || o2 == NULL_NODE) return -1;
      if (o1 instanceof Comparable && o2 instanceof Comparable) {
        final int selfcompared = ((Comparable<Usage>)o1).compareTo(o2);
        if (selfcompared != 0) return selfcompared;

        if (o1 instanceof UsageInFile && o2 instanceof UsageInFile) {
          UsageInFile u1 = (UsageInFile)o1;
          UsageInFile u2 = (UsageInFile)o2;

          VirtualFile f1 = u1.getFile();
          VirtualFile f2 = u2.getFile();

          if (f1 != null && f1.isValid() && f2 != null && f2.isValid()) {
            return f1.getPresentableUrl().compareTo(f2.getPresentableUrl());
          }
        }

        return 0;
      }
      return -1;
    }
  };
  @NonNls private static final String HELP_ID = "ideaInterface.find";
  private UsageContextPanel myCurrentUsageContextPanel;
  private List<UsageContextPanel.Provider> myUsageContextPanelProviders;
  private UsageContextPanel.Provider myCurrentUsageContextProvider;

  private JPanel myCentralPanel;
  private final GroupNode myRoot;
  private final UsageViewTreeModelBuilder myModel;
  private final Object lock = new Object();
  private Splitter myPreviewSplitter;

  public UsageViewImpl(@NotNull final Project project,
                       @NotNull UsageViewPresentation presentation,
                       @NotNull UsageTarget[] targets,
                       Factory<UsageSearcher> usageSearcherFactory) {
    myPresentation = presentation;
    myTargets = targets;
    myUsageSearcherFactory = usageSearcherFactory;
    myProject = project;
    myTree = new Tree() {
      {
        ToolTipManager.sharedInstance().registerComponent(this);
      }
      @Override
      public String getToolTipText(MouseEvent e) {
        TreePath path = getPathForLocation(e.getX(), e.getY());
        if (path != null) {
          if (getCellRenderer() instanceof UsageViewTreeCellRenderer) {
            return UsageViewTreeCellRenderer.getTooltipText(path.getLastPathComponent());
          }
        }
        return null;
      }

      @Override
      public boolean isPathEditable(final TreePath path) {
        return path.getLastPathComponent() instanceof UsageViewTreeModelBuilder.TargetsRootNode;
      }
    };
    myRootPanel = new MyPanel(myTree);
    Disposer.register(this, myRootPanel);
    myModelTracker = new UsageModelTracker(project);
    Disposer.register(this, myModelTracker);

    myModel = new UsageViewTreeModelBuilder(myPresentation, targets);
    myRoot = (GroupNode)myModel.getRoot();
    myBuilder = new UsageNodeTreeBuilder(myTargets, getActiveGroupingRules(project), getActiveFilteringRules(project), myRoot);

    final MessageBusConnection messageBusConnection = myProject.getMessageBus().connect(this);
    messageBusConnection.subscribe(UsageFilteringRuleProvider.RULES_CHANGED, new Runnable() {
      @Override
      public void run() {
        rulesChanged();
      }
    });

    if (!myPresentation.isDetachedMode()) {
      UIUtil.invokeLaterIfNeeded(new Runnable() {
        @Override
        public void run() {
          // lock here to avoid concurrent execution of this init and dispose in other thread
          synchronized (lock) {
            if (isDisposed) return;
            myTree.setModel(myModel);

            myRootPanel.setLayout(new BorderLayout());

            SimpleToolWindowPanel toolWindowPanel = new SimpleToolWindowPanel(false, true);
            myRootPanel.add(toolWindowPanel, BorderLayout.CENTER);

            JPanel toolbarPanel = new JPanel(new BorderLayout());
            toolbarPanel.add(createActionsToolbar(), BorderLayout.WEST);
            toolbarPanel.add(createFiltersToolbar(), BorderLayout.CENTER);
            toolWindowPanel.setToolbar(toolbarPanel);

            myCentralPanel = new JPanel(new BorderLayout());
            setupCentralPanel();

            initTree();
            toolWindowPanel.setContent(myCentralPanel);

            myTree.setCellRenderer(new UsageViewTreeCellRenderer(UsageViewImpl.this));
            collapseAll();

            myModelTracker.addListener(UsageViewImpl.this);

            if (myPresentation.isShowCancelButton()) {
              addButtonToLowerPane(new Runnable() {
                @Override
                public void run() {
                  close();
                }
              }, UsageViewBundle.message("usage.view.cancel.button"));
            }

            myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
              @Override
              public void valueChanged(final TreeSelectionEvent e) {
                SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                    if (isDisposed || myProject.isDisposed()) return;
                    updateOnSelectionChanged();
                  }
                });
              }
            });
          }
        }
      });
    }
    myTransferToEDTQueue = new TransferToEDTQueue<Runnable>("Insert usages", new Processor<Runnable>() {
      @Override
      public boolean process(Runnable runnable) {
        runnable.run();
        return true;
      }
    }, new Condition<Object>() {
      @Override
      public boolean value(Object o) {
        return isDisposed || project.isDisposed() || searchHasBeenCancelled();
      }
    },200);
  }

  protected boolean searchHasBeenCancelled() {
    return false;
  }
  
  protected void setCurrentSearchCancelled(boolean flag){}
  
  private void setupCentralPanel() {
    myCentralPanel.removeAll();
    disposeUsageContextPanels();

    JScrollPane treePane = ScrollPaneFactory.createScrollPane(myTree);
    myPreviewSplitter = new Splitter(false, 0.5f, 0.1f, 0.9f);
    myPreviewSplitter.setFirstComponent(treePane);

    myCentralPanel.add(myPreviewSplitter, BorderLayout.CENTER);

    if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) {
      myPreviewSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS);
      treePane.putClientProperty(UIUtil.KEEP_BORDER_SIDES, SideBorder.RIGHT);
      final JBRadioTabbedPane tabbedPane = new JBRadioTabbedPane(SwingConstants.BOTTOM);

      UsageContextPanel.Provider[] extensions = Extensions.getExtensions(UsageContextPanel.Provider.EP_NAME, myProject);
      myUsageContextPanelProviders = ContainerUtil.filter(extensions, new Condition<UsageContextPanel.Provider>() {
        @Override
        public boolean value(UsageContextPanel.Provider provider) {
          return provider.isAvailableFor(UsageViewImpl.this);
        }
      });
      for (UsageContextPanel.Provider provider : myUsageContextPanelProviders) {
        JComponent component;
        if (myCurrentUsageContextProvider == null || myCurrentUsageContextProvider == provider) {
          myCurrentUsageContextProvider = provider;
          myCurrentUsageContextPanel = provider.create(this);
          component = myCurrentUsageContextPanel.createComponent();
        }
        else {
          component = new JLabel();
        }

        tabbedPane.addTab(provider.getTabTitle(), component);
      }
      int index = myUsageContextPanelProviders.indexOf(myCurrentUsageContextProvider);
      tabbedPane.setSelectedIndex(index);
      tabbedPane.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
          int currentIndex = tabbedPane.getSelectedIndex();
          UsageContextPanel.Provider selectedProvider = myUsageContextPanelProviders.get(currentIndex);
          if (selectedProvider != myCurrentUsageContextProvider) {
            tabSelected(selectedProvider);
          }
        }
      });

      myPreviewSplitter.setSecondComponent(tabbedPane);
    }
    else {<commit_msg>TabbedPane<commit_after>/*
 * Copyright 2000-2009 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.usages.impl;

import com.intellij.find.FindManager;
import com.intellij.icons.AllIcons;
import com.intellij.ide.*;
import com.intellij.ide.actions.CloseTabToolbarAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.*;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.ui.content.Content;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usageView.UsageViewManager;
import com.intellij.usages.*;
import com.intellij.usages.rules.*;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author max
 */
public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTrackerListener {
  @NonNls public static final String SHOW_RECENT_FIND_USAGES_ACTION_ID = "UsageView.ShowRecentFindUsages";
  private static final boolean EXPAND_ALL = Registry.is("find.usage.expand.all");

  private final UsageNodeTreeBuilder myBuilder;
  private final MyPanel myRootPanel;
  private final JTree myTree;
  private Content myContent;

  private final UsageViewPresentation myPresentation;
  private final UsageTarget[] myTargets;
  private final Factory<UsageSearcher> myUsageSearcherFactory;
  private final Project myProject;

  private boolean mySearchInProgress = true;
  private ExporterToTextFile myTextFileExporter;
  private final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);

  private final UsageModelTracker myModelTracker;
  private final Map<Usage, UsageNode> myUsageNodes = new ConcurrentHashMap<Usage, UsageNode>();
  public static final UsageNode NULL_NODE = new UsageNode(NullUsage.INSTANCE, new UsageViewTreeModelBuilder(new UsageViewPresentation(), UsageTarget.EMPTY_ARRAY));
  private final ButtonPanel myButtonPanel = new ButtonPanel();
  private volatile boolean isDisposed;
  private volatile boolean myChangesDetected = false;
  static final Comparator<Usage> USAGE_COMPARATOR = new Comparator<Usage>() {
    @Override
    public int compare(final Usage o1, final Usage o2) {
      if (o1 == NULL_NODE || o2 == NULL_NODE) return -1;
      if (o1 instanceof Comparable && o2 instanceof Comparable) {
        final int selfcompared = ((Comparable<Usage>)o1).compareTo(o2);
        if (selfcompared != 0) return selfcompared;

        if (o1 instanceof UsageInFile && o2 instanceof UsageInFile) {
          UsageInFile u1 = (UsageInFile)o1;
          UsageInFile u2 = (UsageInFile)o2;

          VirtualFile f1 = u1.getFile();
          VirtualFile f2 = u2.getFile();

          if (f1 != null && f1.isValid() && f2 != null && f2.isValid()) {
            return f1.getPresentableUrl().compareTo(f2.getPresentableUrl());
          }
        }

        return 0;
      }
      return -1;
    }
  };
  @NonNls private static final String HELP_ID = "ideaInterface.find";
  private UsageContextPanel myCurrentUsageContextPanel;
  private List<UsageContextPanel.Provider> myUsageContextPanelProviders;
  private UsageContextPanel.Provider myCurrentUsageContextProvider;

  private JPanel myCentralPanel;
  private final GroupNode myRoot;
  private final UsageViewTreeModelBuilder myModel;
  private final Object lock = new Object();
  private Splitter myPreviewSplitter;

  public UsageViewImpl(@NotNull final Project project,
                       @NotNull UsageViewPresentation presentation,
                       @NotNull UsageTarget[] targets,
                       Factory<UsageSearcher> usageSearcherFactory) {
    myPresentation = presentation;
    myTargets = targets;
    myUsageSearcherFactory = usageSearcherFactory;
    myProject = project;
    myTree = new Tree() {
      {
        ToolTipManager.sharedInstance().registerComponent(this);
      }
      @Override
      public String getToolTipText(MouseEvent e) {
        TreePath path = getPathForLocation(e.getX(), e.getY());
        if (path != null) {
          if (getCellRenderer() instanceof UsageViewTreeCellRenderer) {
            return UsageViewTreeCellRenderer.getTooltipText(path.getLastPathComponent());
          }
        }
        return null;
      }

      @Override
      public boolean isPathEditable(final TreePath path) {
        return path.getLastPathComponent() instanceof UsageViewTreeModelBuilder.TargetsRootNode;
      }
    };
    myRootPanel = new MyPanel(myTree);
    Disposer.register(this, myRootPanel);
    myModelTracker = new UsageModelTracker(project);
    Disposer.register(this, myModelTracker);

    myModel = new UsageViewTreeModelBuilder(myPresentation, targets);
    myRoot = (GroupNode)myModel.getRoot();
    myBuilder = new UsageNodeTreeBuilder(myTargets, getActiveGroupingRules(project), getActiveFilteringRules(project), myRoot);

    final MessageBusConnection messageBusConnection = myProject.getMessageBus().connect(this);
    messageBusConnection.subscribe(UsageFilteringRuleProvider.RULES_CHANGED, new Runnable() {
      @Override
      public void run() {
        rulesChanged();
      }
    });

    if (!myPresentation.isDetachedMode()) {
      UIUtil.invokeLaterIfNeeded(new Runnable() {
        @Override
        public void run() {
          // lock here to avoid concurrent execution of this init and dispose in other thread
          synchronized (lock) {
            if (isDisposed) return;
            myTree.setModel(myModel);

            myRootPanel.setLayout(new BorderLayout());

            SimpleToolWindowPanel toolWindowPanel = new SimpleToolWindowPanel(false, true);
            myRootPanel.add(toolWindowPanel, BorderLayout.CENTER);

            JPanel toolbarPanel = new JPanel(new BorderLayout());
            toolbarPanel.add(createActionsToolbar(), BorderLayout.WEST);
            toolbarPanel.add(createFiltersToolbar(), BorderLayout.CENTER);
            toolWindowPanel.setToolbar(toolbarPanel);

            myCentralPanel = new JPanel(new BorderLayout());
            setupCentralPanel();

            initTree();
            toolWindowPanel.setContent(myCentralPanel);

            myTree.setCellRenderer(new UsageViewTreeCellRenderer(UsageViewImpl.this));
            collapseAll();

            myModelTracker.addListener(UsageViewImpl.this);

            if (myPresentation.isShowCancelButton()) {
              addButtonToLowerPane(new Runnable() {
                @Override
                public void run() {
                  close();
                }
              }, UsageViewBundle.message("usage.view.cancel.button"));
            }

            myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
              @Override
              public void valueChanged(final TreeSelectionEvent e) {
                SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                    if (isDisposed || myProject.isDisposed()) return;
                    updateOnSelectionChanged();
                  }
                });
              }
            });
          }
        }
      });
    }
    myTransferToEDTQueue = new TransferToEDTQueue<Runnable>("Insert usages", new Processor<Runnable>() {
      @Override
      public boolean process(Runnable runnable) {
        runnable.run();
        return true;
      }
    }, new Condition<Object>() {
      @Override
      public boolean value(Object o) {
        return isDisposed || project.isDisposed() || searchHasBeenCancelled();
      }
    },200);
  }

  protected boolean searchHasBeenCancelled() {
    return false;
  }
  
  protected void setCurrentSearchCancelled(boolean flag){}
  
  private void setupCentralPanel() {
    myCentralPanel.removeAll();
    disposeUsageContextPanels();

    JScrollPane treePane = ScrollPaneFactory.createScrollPane(myTree);
    myPreviewSplitter = new Splitter(false, 0.5f, 0.1f, 0.9f);
    myPreviewSplitter.setFirstComponent(treePane);

    myCentralPanel.add(myPreviewSplitter, BorderLayout.CENTER);

    if (UsageViewSettings.getInstance().IS_PREVIEW_USAGES) {
      myPreviewSplitter.setProportion(UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS);
      treePane.putClientProperty(UIUtil.KEEP_BORDER_SIDES, SideBorder.RIGHT);
      final JBTabbedPane tabbedPane = new JBTabbedPane(SwingConstants.BOTTOM){
        @NotNull
        @Override
        protected Insets getInsetsForTabComponent() {
          return new Insets(0,0,0,0);
        }
      };

      UsageContextPanel.Provider[] extensions = Extensions.getExtensions(UsageContextPanel.Provider.EP_NAME, myProject);
      myUsageContextPanelProviders = ContainerUtil.filter(extensions, new Condition<UsageContextPanel.Provider>() {
        @Override
        public boolean value(UsageContextPanel.Provider provider) {
          return provider.isAvailableFor(UsageViewImpl.this);
        }
      });
      for (UsageContextPanel.Provider provider : myUsageContextPanelProviders) {
        JComponent component;
        if (myCurrentUsageContextProvider == null || myCurrentUsageContextProvider == provider) {
          myCurrentUsageContextProvider = provider;
          myCurrentUsageContextPanel = provider.create(this);
          component = myCurrentUsageContextPanel.createComponent();
        }
        else {
          component = new JLabel();
        }

        tabbedPane.addTab(provider.getTabTitle(), component);
      }
      int index = myUsageContextPanelProviders.indexOf(myCurrentUsageContextProvider);
      tabbedPane.setSelectedIndex(index);
      tabbedPane.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
          int currentIndex = tabbedPane.getSelectedIndex();
          UsageContextPanel.Provider selectedProvider = myUsageContextPanelProviders.get(currentIndex);
          if (selectedProvider != myCurrentUsageContextProvider) {
            tabSelected(selectedProvider);
          }
        }
      });
      tabbedPane.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT));
      myPreviewSplitter.setSecondComponent(tabbedPane);
    }
    else {
{'fraction_non_alphanumeric': 0.0895979020979021, 'fraction_numerical': 0.00405276541640178, 'mean_word_length': 3.5243573611360777, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4333184', 'n_tokens_mistral': 7118, 'n_tokens_neox': 6882, 'n_words': 1445}