SearchResultsPanel.java :  » IDE » Schmortopf » Schmortopf » SearchResults » Java Open Source

Java Open Source » IDE » Schmortopf 
Schmortopf » Schmortopf » SearchResults » SearchResultsPanel.java
package Schmortopf.SearchResults;


import javax.swing.*;                                  
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;



import Schmortopf.Main.IDE_ProjectFrame;
import Schmortopf.Utility.gui.*;
import Language.Language;
import Shared.Logging.Log;                                  


import Schmortopf.Main.FilesTreeProvider;
import Schmortopf.ProjectFiles.ProjectFilesTree.*;
import Schmortopf.Utility.ThreadEngine.ThreadEngine;
import Schmortopf.Utility.Text.*;
import Schmortopf.Utility.IniFile.IniFile;
import Schmortopf.Utility.gui.dialogs.ProgressWindow;
import Schmortopf.Utility.gui.dialogs.TextSearchDialog;
import Schmortopf.Utility.SchmortopfConstants;
import Schmortopf.FileComponents.Model.EditableLeafObject;
import Schmortopf.Libraries.LibrariesTree;
import Schmortopf.Libraries.LibrariesTreeLeafObject;
import Schmortopf.FileStructure.FileStructureDescriptionFactory;
import Schmortopf.FileStructure.Descriptions.FileStructureDescription;
import Schmortopf.SearchResults.*;
import Schmortopf.Main.GCMemoryChecker;

/**
 *  The panel, which holds and displays search results.
 *  It encapsulates and manages searchresults trees.
 */
public class SearchResultsPanel extends JPanel
{

  // For security and memory limitation, so that searches f.ex. after characters or so
  // which can produce hundred thousands of hits don't blow up the search tree.
  private static final int MaximumNumberOfHits = 10000;

  private JContrastLabel searchResultsLabel = new JContrastLabel(Language.Translate("Search Results"));
  
  private IDE_ProjectFrame projectFrame;

  private JTabbedPane tabPane;

  private String memorized_SearchText = null;
  private boolean memorized_DoCaseSensitiveSearch = false;
  private boolean memorized_DoWholeWordsSearch = false;
    



  public SearchResultsPanel( IDE_ProjectFrame _projectFrame ) {
    this.projectFrame = _projectFrame;

    // The tab, which contains the search results tree's:
    this.tabPane = new JTabbedPane();
    
    final JScrollPane treeScrollPane = new JScrollPane(this.tabPane);
    treeScrollPane.setBorder( BorderFactory.createEmptyBorder(0,0,0,0) );
    // Allow Swing to decrease this size to zero :
    treeScrollPane.setMinimumSize( new Dimension(0,0) );

    this.setLayout( new BorderLayout(0,0) );
    
    // the title panel:
    JPanel searchResultsTitlePanel  = new EFCNSmoothBackgroundPanel( new FlowLayout(FlowLayout.CENTER,0,0), EFCNSmoothBackgroundPanel.PanelBackGroundColorIdentifier, EFCNSmoothBackgroundPanel.SmoothCenterMode );
    searchResultsLabel.setHorizontalAlignment(SwingConstants.CENTER);
    searchResultsLabel.setBorder( BorderFactory.createEmptyBorder(0,0,0,0) );
    searchResultsTitlePanel.add( this.searchResultsLabel );
    // add it :
    this.add(searchResultsTitlePanel,BorderLayout.NORTH);
    this.add( treeScrollPane ,BorderLayout.CENTER);
  } // Constructor

  
  
  
  
  
  public void updateUI() {
    super.updateUI();
    this.setBackground( UIManager.getColor("Textfield.background"));                  
  }


  public void initializeSearchResults( String searchName, String searchMessage ) {
    // Get the search results tree associated with the tab
    // with title searchName. The tab is created, if it does
    // not exist:
    SearchResultsTree searchResultsTree =
      this.getSearchResultsTreeForTabWithTitle(searchName);
    // and initialize this tree:
    searchResultsTree.initializeTreeWithSingleNode(searchMessage);
    this.selectTabWithSearchResultsTree(searchResultsTree);
  }   




  /**
   *  Called by the editorpanel.
   *  Controler method, delegated to the searchResultsTree.
   *  Information goes from editorpanel (back) to the searchResultsTree.
   */
   public void searchTheCompleteProjectForText( String searchName,
                                                String searchText,
                                                boolean doCaseSensitiveSearch,
                                                boolean doApproximateSearch,
                                                boolean doWholeWordsSearch,
                                                final boolean doSearchComments,
                                                final boolean doIncludeProjectFiles,
                                                final boolean doIncludeLibraries,
                                                final int approximateSearchMethodIndex,
                                                final int approximateSearchTolerance    )
   {
     // Delegate:
     // Get the search results tree associated with the tab
     // with title searchName. The tab is created, if it does
     // not exist:
     SearchResultsTree searchResultsTree =
       this.getSearchResultsTreeForTabWithTitle(searchName);
     this.searchTheCompleteProjectForText( searchResultsTree,searchText,
                                           doCaseSensitiveSearch,doWholeWordsSearch,
                                           doApproximateSearch,doSearchComments,
                                           doIncludeProjectFiles,doIncludeLibraries,
                                           approximateSearchMethodIndex,
                                           approximateSearchTolerance);
   } // searchTheCompleteProjectForText





  /**
   *  Starts the project global search process and
   *  displays the results in this tree view.
   */                              
   public void searchTheCompleteProjectForText( final SearchResultsTree searchResultsTree,
                                                final String searchText,
                                                final boolean doCaseSensitiveSearch,
                                                final boolean doWholeWordsSearch,
                                                final boolean doApproximateSearch,
                                                final boolean doSearchComments,
                                                final boolean doIncludeProjectFiles,
                                                final boolean doIncludeLibraries,
                                                final int approximateSearchMethodIndex,
                                                final int approximateSearchTolerance    )
   {         
     SearchResultsTreeModel model = (SearchResultsTreeModel)searchResultsTree.getModel(); 
     model.initializeModel(Language.Translate("Searching")+"...");
     Runnable searchRunnable = new Runnable()
      {
        public void run()
        {
          //long startTime = System.currentTimeMillis();
          internal_searchTheCompleteProjectForText( searchResultsTree,searchText,
                                                    doCaseSensitiveSearch,doWholeWordsSearch,
                                                    doApproximateSearch,doSearchComments,
                                                    doIncludeProjectFiles,doIncludeLibraries,
                                                    approximateSearchMethodIndex,approximateSearchTolerance );

          //long elapsedTime = (System.currentTimeMillis()-startTime)/1000;
          //Log.Info("SEARCH: Elapsed time= " + elapsedTime + " [s]");
        }
      };
     ThreadEngine.getInstance().addRunnable(searchRunnable,"Project Search Task");
   } // searchTheCompleteProjectForText


             
       

  /**                
   *  Called from above in an EngineThread.
   */
   private void internal_searchTheCompleteProjectForText( final SearchResultsTree searchResultsTree,
                                                          final String searchText,
                                                          final boolean doCaseSensitiveSearch,
                                                          final boolean doWholeWordsSearch,
                                                          final boolean doApproximateSearch,
                                                          final boolean doSearchComments,
                                                          final boolean doIncludeProjectFiles,
                                                          final boolean doIncludeLibraries,
                                                          final int approximateSearchMethodIndex,
                                                          final int approximateSearchTolerance  )
   {
               
     // Test for thread design error : It must be outside the EDT here :
     if( EventQueue.isDispatchThread() )
      {
        JOptionPane.showMessageDialog( this.projectFrame.getParentFrameForChildren(),"SearchResultsTree.searchTheCompleteProjectForText(): \nDesignerror : Called inside EDT. Cancelled.");
        return;
      }
     ProjectFilesTree projectFilesTree = this.projectFrame.getProjectFilesManager().getProjectFilesTree();
     LibrariesTree librariesTree = this.projectFrame.getLibrariesTree();
      
     // Add all leafs to this vector :      
     Vector leafVector = new Vector();

     // Add all projectfilestree leafs, if the associate checkbox has been selected :
     if( doIncludeProjectFiles )
      {
        final String[] project_SourceFilePathes = projectFilesTree.getAllSourceFilePathes(false);
        for( int i=0; i < project_SourceFilePathes.length; i++ )
         {
           EditableLeafObject leaf = projectFilesTree.getLeafForNodeWithPathName( project_SourceFilePathes[i] );
           leafVector.addElement(leaf);
         }
      }
     // Add all library leafs, if the associate checkbox has been selected :
     if( doIncludeLibraries )
      {
        EditableLeafObject[] libLeafs = librariesTree.getAllLeafs();
        for( int i=0; i < libLeafs.length; i++ )
         {
           leafVector.addElement( libLeafs[i] );
         }
      }
     String progressMultiLineText = null;
     if(  doIncludeProjectFiles && !doIncludeLibraries )
      {
        progressMultiLineText = Language.Translate("Searching the project.")+"\n"+Language.Translate("Results are displayed in the\nsearch-results tree on the left");
      }
     else
     if(  !doIncludeProjectFiles && doIncludeLibraries )
      {
        progressMultiLineText = Language.Translate("Searching the library.")+"\n"+Language.Translate("Results are displayed in the\nsearch-results tree on the left");
      }
     else
      {
        progressMultiLineText = Language.Translate("Searching the project and the library.")+"\n"+Language.Translate("Results are displayed in the\nsearch-results tree on the left");
      }

     this.searchLeafs( searchResultsTree,
                       leafVector,progressMultiLineText,
                       searchText,
                       doCaseSensitiveSearch,doWholeWordsSearch,
                       doApproximateSearch,doSearchComments,
                       doIncludeLibraries,
                       approximateSearchMethodIndex,approximateSearchTolerance );

     // GC friendly: Do some cleanup, which make its work easier:
     leafVector.removeAllElements();
     leafVector = null;
     projectFilesTree = null;
     librariesTree = null;

     this.selectTabWithSearchResultsTree(searchResultsTree);

     System.gc(); // Remove collateral damage

   } // searchTheCompleteProjectForText


   





   public void searchLeafs(  final SearchResultsTree searchResultsTree,
                             Vector leafVector,
                             final String progressMultiLineText,
                             final String searchText,
                             final boolean doCaseSensitiveSearch,
                             final boolean doWholeWordsSearch,
                             final boolean doApproximateSearch,
                             final boolean doSearchComments,
                             final boolean librariesIncluded,
                             final int approximateSearchMethodIndex,
                             final int approximateSearchTolerance )
   {

     if( EventQueue.isDispatchThread() )
      {
        Log.Error("DESIGNERROR:");
        Log.Error("Must be called OUTSIDE the Swing EDT. Returning immediately.");
        return;
      }

     ProjectFilesTree projectFilesTree = this.projectFrame.getProjectFilesManager().getProjectFilesTree();
     LibrariesTree librariesTree = this.projectFrame.getLibrariesTree();

     // Unload all contents, which maybe allows the GC to decrease the JVM memory,
     // if no accessed blocks somewhere far from the main memory pool exist:
     this.projectFrame.getProjectFilesManager().unloadAllUnchangedAndNotEditedFiles();
     librariesTree.unloadAllNotEditedFiles();

     boolean cancelledByUser = false;
     final long startTime = System.currentTimeMillis();
     // Create the ProgressWindow with cancel option :
     final ProgressWindow progressWindow =
       new ProgressWindow( progressMultiLineText,null,
                           this.projectFrame.getParentFrameForChildren(),
                           this.projectFrame.getMainFrameProvider(),
                           true );
     progressWindow.setProgressMaxValue( leafVector.size() );
     int progressStepSize = 1+leafVector.size()/30;
     try
      {
        EventQueue.invokeAndWait( new Runnable()
         {
           public void run()
           {
             progressWindow.showCentered();
           }
         });
        Thread.sleep(33);
      }
     catch( Exception e9524876 ){}

     GCMemoryChecker.getInstance().checkMemory(false,true); // GC management

     // Go through all, but note, that we not use the buffer mechanism,
     // but use the getText_fast_withoutDocumentCreation() methods, which
     // bypass the memory management of the IDE and don't load contents
     // into the leafs. Therefore no unload() calls are necessary.
     final Vector searchResultsVector = new Vector();
     boolean doContinueSearch = true; // Cleared, if the maximum number of search hits
                                      // has been reached.
     IntegerIntervall[] searchIntervalls = null;
     for( int i=0; i < leafVector.size(); i++ )
      {
        // Break, if the user had cancelled it :
        if( progressWindow.getWasCancelled() )
         {
           cancelledByUser = true;
           break;
         }
        EditableLeafObject leaf = (EditableLeafObject)leafVector.elementAt(i);
        String fileName = leaf.getName();
        String filePathName = leaf.getFilePathName();
        // Now we get the associated text of this file. Note, that using getText()
        // this automatically would cause load on demand and creation of a document,
        // if it's not already in the memory.
        // Therefore we use a fast variant called getText_fast_withoutDocumentCreation(),
        // which doesnt create a document, but just gets the text in a StringBuffer.
        // This method looks, if the content is available in the leaf content and gets
        // it from there, or otherwise gets it directly from the disk bypassing
        // document creation :
        StringBuffer textBuffer = leaf.getText_fast_withoutDocumentCreation();
        searchIntervalls = null; // null -> search all the text
        if( !doSearchComments )
         {
           // searchIntervalls contains all non-comment intervalls
           searchIntervalls = TextUtilities.GetAllNonCommentIntervalls(textBuffer);
         }
        // Get all occurences of the searched text inside the searchIntervalls:
        doContinueSearch = this.addSearchTextOccurencesToVector( searchText,
                                                                 doCaseSensitiveSearch,
                                                                 doWholeWordsSearch,
                                                                 doApproximateSearch,
                                                                 approximateSearchMethodIndex,
                                                                 approximateSearchTolerance,
                                                                 searchIntervalls,
                                                                 textBuffer,
                                                                 fileName,
                                                                 filePathName,
                                                                 searchResultsVector,
                                                                 leaf );
        if( !doContinueSearch ) // MaximumNumberOfHits reached
         {
           break;
         }
        if( i % progressStepSize == 0 )
         {
          final int iFinal = i;
          try
           {
             EventQueue.invokeAndWait( new Runnable()
              {
                public void run()
                {
                  progressWindow.setProgressValue(iFinal);
                }
              });
             Thread.yield();
           }
          catch( Exception e9524876 ){}
         }
        if( i % 20 == 0 )
         {
           GCMemoryChecker.getInstance().checkMemory(false,false); // GC management
         }
      } // for

     GCMemoryChecker.getInstance().checkMemory(false,false); // GC management

     if( !cancelledByUser )
      {
       try
        {
          EventQueue.invokeAndWait( new Runnable()
           {
             public void run()
             {
               progressWindow.setVisible(false);
               progressWindow.dispose();
               // Add the search results to this tree ui :
               SearchResultsUserObject[] resultObjects = new SearchResultsUserObject[searchResultsVector.size()];
               searchResultsVector.copyInto(resultObjects);
               SearchResultsTreeModel model = (SearchResultsTreeModel)searchResultsTree.getModel(); 
               model.initializeTreeWith( resultObjects );
               // and if #hits > 0, make sure, the searchresultstree becomes visible,
               // by moving the splitpane a bit, if needed :
               projectFrame.popupSearchResultsTreePanel();
             }
           });
          Thread.sleep(33);
        }
       catch( Exception e9524876 ){}
      } // if not cancelledByUser

     // Feedback:
     if( !doContinueSearch ) // MaximumNumberOfHits reached
      {
        String message = Language.Translate("The search has been stopped, after more than % hits have been found. The results therefore are incomplete.\nPlease formulate your search more specific.", ""+MaximumNumberOfHits);
        JOptionPane.showMessageDialog(this.projectFrame.getParentFrameForChildren(), message, Language.Translate("Information"), JOptionPane.WARNING_MESSAGE);
      }

     // GC friendly: Do some cleanup, which make its work easier:
     leafVector.removeAllElements();
     leafVector = null;
     projectFilesTree = null;
     librariesTree = null;

     GCMemoryChecker.getInstance().checkMemory(true,false); // GC management

   } // searchLeafs





  /**                     
   *  Adds all hits in the file defined by filePathName.
   *  Returns false, if the maximum number of hits is reached.
   *
   *  If the user has chosen to exclude comments, the passed searchIntervalls
   *  contain all non-comment intervalls, otherwise its null.
   */
   private boolean addSearchTextOccurencesToVector( final String rawSearchedText,
                                                    final boolean doCaseSensitiveSearch,
                                                    final boolean doWholeWordsSearch,
                                                    final boolean doApproximateSearch,
                                                    final int approximateSearchMethodIndex,
                                                    final int approximateSearchTolerance,
                                                    final IntegerIntervall[] searchIntervalls,
                                                    final StringBuffer textBuffer,
                                                    final String fileName,
                                                    final String filePathName,
                                                    final Vector resultTargetVector,
                                                    final EditableLeafObject editableLeafObject )
   {
     boolean doContinueSearch = true; // Returned parameter. Set to false, once
                                      // the maximum number of hits is reached.
     int searchedTextLength = rawSearchedText.length();
     if( searchedTextLength > 0 )
      {

       //ystem.out.println("[SearchResultsTree] Search in file " + fileName );

       int[] foundPositions = SearchMethods.SearchTextOccurences( rawSearchedText,
                                                                  doCaseSensitiveSearch,
                                                                  doWholeWordsSearch,
                                                                  doApproximateSearch,
                                                                  approximateSearchMethodIndex,
                                                                  approximateSearchTolerance,
                                                                  textBuffer,
                                                                  false /*==search all the text */ );
       //ystem.out.println("COMPLETED.");
       int searchIndex;
       for( int i=0; i < foundPositions.length; i++ )
        {
          searchIndex = foundPositions[i];
          boolean addThisSearchHit = true;
          if( searchIntervalls != null )
           {
             addThisSearchHit = TextUtilities.GetIsIndexContainedIn(searchIndex,searchIntervalls);
           }
          if( addThisSearchHit )
           {
              int lineNumber = this.getLineNumberForPosition( searchIndex,editableLeafObject.getContent() );
              SearchResultsUserObject entry = new SearchResultsUserObject( editableLeafObject,
                                                                           lineNumber,
                                                                           searchIndex,
                                                                           searchedTextLength );
              resultTargetVector.addElement(entry);
              // Size limitation : Break when we reach MaximumNumberOfHits added entries :
              if( resultTargetVector.size() >= MaximumNumberOfHits )
               {
                 doContinueSearch = false;
                 break;
               }
           } // if addThisSearchHit
        } // for
      } // if
     return doContinueSearch;
   } // addSearchTextOccurencesToVector






   private int getLineNumberForPosition( final int position,
                                         final Object document )
   {
     int lineNumber = 0;
     if( document == null ) // error test
      {
        Log.Warn("Document is null.");
      }           
     else // Projectfiles carry a DefaultStyledDocument :
     if( document instanceof DefaultStyledDocument )
      {
        final DefaultStyledDocument doc = (DefaultStyledDocument)document;
        final Element rootElement = doc.getDefaultRootElement();
        for( int i=0; i < rootElement.getElementCount(); i++ )
         {
           final Element element = rootElement.getElement(i);
           if( ( element.getStartOffset() <= position ) &&
               ( element.getEndOffset() > position   )    )
            {
              lineNumber = i;
              break;
            }
         }
      }
     else // library java files carry text :
     if( document instanceof StringBuffer )
      {
        String text = ((StringBuffer)document).toString();
        // This is for text files [ jar file entries ]
        lineNumber = -1;
        int workPosition = 0;
        while( workPosition < position )
         {
           workPosition = text.indexOf('\n',workPosition+1);
           if( workPosition >= text.length()-1 ) break;
           lineNumber++;
         }
      }
     else // library class files carry a filestructuredescription :
     if( document instanceof FileStructureDescription )
      {
        FileStructureDescription fsd = (FileStructureDescription)document;
        String text = FileStructureDescriptionFactory.GetJavaSourceCompatibleTextDescriptionFor(fsd);
        // This is for text files [ jar file entries ]
        lineNumber = -1;
        int workPosition = 0;
        while( workPosition < position )
         {
           workPosition = text.indexOf('\n',workPosition+1);
           if( workPosition >= text.length()-1 ) break;
           lineNumber++;
         }
      }
     else
      {      
        String docTypeName = "unknown";
        if( document != null )
         {
           if( document.getClass() != null )
            {
              if( document.getClass().getName() != null )
               {
                 docTypeName = document.getClass().getName();
               }
            }
         }
        Log.Warn("CAUTION: Not supported doc type = " + docTypeName );
        Log.Warn("Returning zero.");
      }
     return lineNumber;
   }







  /**
   *   This is called from the SymbolUsageLocationSearch, which passes
   *   its results to this tree.
   */
   public void setObjectSearchResults( final String searchName,
                                       final SearchResultsUserObject[] searchResultsUserObjects ) {
     // Delegate:
     // Get the search results tree associated with the tab
     // with title searchName. The tab is created, if it does
     // not exist:
     SearchResultsTree searchResultsTree =
       this.getSearchResultsTreeForTabWithTitle(searchName);
     searchResultsTree.setTreeContentWithObjectSearchResults(searchResultsUserObjects);
     this.selectTabWithSearchResultsTree(searchResultsTree);
   }



  /**
   *  Called by the projectframe.
   *  Starts the search process and
   *  displays the results in this tree view.
   */
   public void searchProjectDirectoryForText( final String searchName,
                                              final DefaultMutableTreeNode directoryNode ) {
     ProjectFilesTree projectFilesTree = this.projectFrame.getProjectFilesManager().getProjectFilesTree();
     this.searchDirectoryForText( searchName, directoryNode,projectFilesTree );
   }


  /**
   *  Called by the projectframe.
   *  Starts the search process and
   *  displays the results in this tree view.
   */
   public void searchLibraryDirectoryForText( final String searchName,
                                              final DefaultMutableTreeNode directoryNode ) {
     LibrariesTree librariesTree = this.projectFrame.getLibrariesTree();
     this.searchDirectoryForText( searchName,directoryNode,librariesTree );
   } // searchLibraryDirectoryForText

   
   
   


   private void searchDirectoryForText( final String searchName,
                                        final DefaultMutableTreeNode directoryNode,
                                        final FilesTreeProvider filesTreeProvider )
   {
   // Delegate:
   // Get the search results tree associated with the tab
   // with title searchName. The tab is created, if it does
   // not exist:
   final SearchResultsTree searchResultsTree =
     this.getSearchResultsTreeForTabWithTitle(searchName);
    TextSearchDialog searchDialog =
         new TextSearchDialog( this.projectFrame.getParentFrameForChildren(),
                               this.projectFrame.getMainFrameProvider().getGlobalIniFile(),
                               false,false,
                               0,
                               this.projectFrame.getMainFrameProvider() );
    if( memorized_SearchText  != null )
     {
       searchDialog.setSearchText( this.memorized_SearchText   );
       searchDialog.setDoCaseSensitiveSearch( this.memorized_DoCaseSensitiveSearch );
       searchDialog.setDoWholeWordsSearch( this.memorized_DoWholeWordsSearch );
     }
    searchDialog.setTitle( Language.Translate("Directory Text Search") );
    // Here, we always preset project search :
    searchDialog.lockGlobalSearch(); // local search would be fancy (no results come back, instead editor shows them)
    searchDialog.show();
    this.memorized_DoCaseSensitiveSearch = searchDialog.getDoCaseSensitiveSearch();
    this.memorized_DoWholeWordsSearch = searchDialog.getDoWholeWordsSearch();
    if( !searchDialog.getDialogWasCancelled() )
     {
       final String searchText = searchDialog.getSearchText();
       if( searchText != null )
        {
         if( searchText.length() > 0 )
          {
            // Store the search attributes for a possible later call
            // of the SearchAgain action :
            this.memorized_SearchText = searchText;
            // Now go search the directory :
            final boolean doCaseSensitiveSearch = searchDialog.getDoCaseSensitiveSearch();
            final boolean doWholeWordsSearch = searchDialog.getDoWholeWordsSearch();
            final boolean doApproximateSearch = searchDialog.getDoApproximateSearch();
            final boolean doSearchComments = searchDialog.getDoSearchComments();
            final boolean doIncludeProjectFiles = true;
            final boolean doIncludeLibraries = false;
            final int approximateSearchMethodIndex = searchDialog.getApproximateSearchMethodIndex();
            final int approximateSearchTolerance   = searchDialog.getApproximateSearchSearchTolerance();
            SearchResultsTreeModel model = (SearchResultsTreeModel)searchResultsTree.getModel();            
            model.initializeModel(Language.Translate("Searching")+"...");
            Runnable searchRunnable = new Runnable()
            {
              public void run()
              {
                 internal_searchDirectoryForText( searchResultsTree,filesTreeProvider,
                                                  searchText,directoryNode,
                                                  doCaseSensitiveSearch,doWholeWordsSearch,
                                                  doApproximateSearch,doSearchComments,
                                                  doIncludeProjectFiles,doIncludeLibraries,
                                                  approximateSearchMethodIndex,approximateSearchTolerance );
              }
            };
            ThreadEngine.getInstance().addRunnable(searchRunnable,"Project Directory Search Task");
          }
        }
     } // if
   } // searchDirectoryForText









  /**
   *  Called from above in an EngineThread.
   */
   private void internal_searchDirectoryForText( final SearchResultsTree searchResultsTree,
                                                 final FilesTreeProvider filesTreeProvider,
                                                 final String searchText,
                                                 final DefaultMutableTreeNode directoryNode,
                                                 final boolean doCaseSensitiveSearch,
                                                 final boolean doWholeWordsSearch,
                                                 final boolean doApproximateSearch,
                                                 final boolean doSearchComments,
                                                 final boolean doIncludeProjectFiles,
                                                 final boolean doIncludeLibraries,
                                                 final int approximateSearchMethodIndex,
                                                 final int approximateSearchTolerance  )
   {
     // Test for thread design error : It must be outside the EDT here :
     if( EventQueue.isDispatchThread() )
      {
        JOptionPane.showMessageDialog( this.projectFrame.getParentFrameForChildren(),"SearchResultsTree.internal_searchDirectoryForText(): \nDesignerror : Called inside EDT. Cancelled.");
        return;
      }
     // Add all leafs to this vector :
     Vector leafVector = new Vector();
     final EditableLeafObject[] leafs = filesTreeProvider.getAllLeafsOfDirectory( directoryNode );
     for( int i=0; i < leafs.length; i++ )
      {
        leafVector.addElement(leafs[i]);
      }
     String progressMultiLineText = Language.Translate("Searching the directory") +
                                    "\n" +
                                    directoryNode.toString() +
                                    "\n" +
                                    Language.Translate("Results are displayed in the\nsearch-results tree on the left");

     this.searchLeafs( searchResultsTree,leafVector,progressMultiLineText,
                       searchText,
                       doCaseSensitiveSearch,doWholeWordsSearch,
                       doApproximateSearch,doSearchComments,
                       false,
                       approximateSearchMethodIndex,approximateSearchTolerance );

     this.selectTabWithSearchResultsTree(searchResultsTree);

     // GC friendly: Do some cleanup, which make its work easier:
     leafVector.removeAllElements();
     leafVector = null;
   } // internal_searchProjectDirectoryForText





   public void searchProjectDirectoryForFilename( final String searchName,
                                                  final DefaultMutableTreeNode directoryNode )
   {
     SearchResultsTree searchResultsTree =
       this.getSearchResultsTreeForTabWithTitle(searchName);
     ProjectFilesTree projectFilesTree = this.projectFrame.getProjectFilesManager().getProjectFilesTree();
     this.searchDirectoryForFilename( searchResultsTree,directoryNode,projectFilesTree );
   }



  /**
   *  Same for libraries
   */
   public void searchLibraryDirectoryForFilename( final String searchName,
                                                  final DefaultMutableTreeNode directoryNode )
   {
     SearchResultsTree searchResultsTree =
       this.getSearchResultsTreeForTabWithTitle(searchName);
     LibrariesTree librariesTree = this.projectFrame.getLibrariesTree();
     this.searchDirectoryForFilename( searchResultsTree,directoryNode,librariesTree );
   }                              



                     
  /**
   *  Used for te projectfilestree as well as the librariestree (both implement
   *  the interface FilesTreeProvider)
   */
   private void searchDirectoryForFilename( final SearchResultsTree searchResultsTree,
                                            final DefaultMutableTreeNode directoryNode,
                                            final FilesTreeProvider filesTreeProvider )
   {                                                                               
    TextSearchDialog searchDialog =                                            
         new TextSearchDialog( this.projectFrame.getParentFrameForChildren(),
                               this.projectFrame.getMainFrameProvider().getGlobalIniFile(),false,false,
                               0,
                               this.projectFrame.getMainFrameProvider() );
    if( memorized_SearchText  != null ) searchDialog.setSearchText( this.memorized_SearchText   );
    searchDialog.setDoCaseSensitiveSearch( this.memorized_DoCaseSensitiveSearch );
    searchDialog.setDoWholeWordsSearch( this.memorized_DoWholeWordsSearch );
    searchDialog.setTitle( Language.Translate("Directory Filename Search") );
    // Here, we always preset project search :
    searchDialog.lockGlobalSearch(); // local search would be fancy (no results come back, instead editor shows them)
    searchDialog.show();
    this.memorized_DoCaseSensitiveSearch = searchDialog.getDoCaseSensitiveSearch();
    this.memorized_DoWholeWordsSearch = searchDialog.getDoWholeWordsSearch();
    if( !searchDialog.getDialogWasCancelled() )
     {
       final String searchText = searchDialog.getSearchText();
       if( searchText != null )
        {
         if( searchText.length() > 0 )
          {
            // Store the search attributes for a possible later call
            // of the SearchAgain action :
            this.memorized_SearchText = searchText;
            // Now go search the directory :
            final boolean doCaseSensitiveSearch = searchDialog.getDoCaseSensitiveSearch();
            final boolean doWholeWordsSearch = searchDialog.getDoWholeWordsSearch();
            final boolean doApproximateSearch = searchDialog.getDoApproximateSearch();
            final boolean doSearchComments = searchDialog.getDoSearchComments();
            final boolean doIncludeProjectFiles = true;
            final boolean doIncludeLibraries = false;
            final int approximateSearchMethodIndex = searchDialog.getApproximateSearchMethodIndex();
            final int approximateSearchTolerance   = searchDialog.getApproximateSearchSearchTolerance();
            Runnable searchRunnable = new Runnable()
            {
              public void run()
              {
                 internal_searchDirectoryForFilename( searchResultsTree,
                                                      filesTreeProvider,
                                                      searchText,directoryNode,
                                                      doCaseSensitiveSearch,doWholeWordsSearch,     
                                                      doApproximateSearch,doSearchComments,
                                                      doIncludeProjectFiles,doIncludeLibraries,
                                                      approximateSearchMethodIndex,approximateSearchTolerance );
              }
            };
            ThreadEngine.getInstance().addRunnable(searchRunnable,"Project Directory Filename Search Task");
          }
        }
     } // if
   } // searchProjectDirectoryForFilename


                


  /**
   *  Called from above in an EngineThread.
   */                            
   private void internal_searchDirectoryForFilename( final SearchResultsTree searchResultsTree,
                                                     final FilesTreeProvider filesTreeProvider,
                                                     final String searchText,         
                                                     final DefaultMutableTreeNode directoryNode,
                                                     final boolean doCaseSensitiveSearch,
                                                     final boolean doWholeWordsSearch,
                                                     final boolean doApproximateSearch,
                                                     final boolean doSearchComments,
                                                     final boolean doIncludeProjectFiles,
                                                     final boolean doIncludeLibraries,
                                                     final int approximateSearchMethodIndex,
                                                     final int approximateSearchTolerance  )
   {
     // Test for thread design error : It must be outside the EDT here :
     if( EventQueue.isDispatchThread() )
      {
        JOptionPane.showMessageDialog( this.projectFrame.getParentFrameForChildren(),
                                       "SearchResultsTree.internal_searchDirectoryForText(): \nDesignerror : Called inside EDT. Cancelled.");
        return;
      }

     // Unload all contents, which maybe allows the GC to decrease the JVM memory,
     // if no accessed blocks somewhere far from the main memory pool exist:
     this.projectFrame.getProjectFilesManager().unloadAllUnchangedAndNotEditedFiles();


     // Create the ProgressWindow with cancel option :
     final ProgressWindow progressWindow =
       new ProgressWindow( "Searching for filename.",null,
                           this.projectFrame.getParentFrameForChildren(),
                           this.projectFrame.getMainFrameProvider(),
                           true );
     try
      {
        EventQueue.invokeAndWait( new Runnable()
         {
           public void run()
           {
             progressWindow.showCentered();
           }
         });
        Thread.sleep(33);
      }
     catch( Exception e9524876 ){}

     // Add all leafs to this vector :
     Vector leafVector = new Vector();
     StringBuffer filenamesTextList = new StringBuffer();     
     final EditableLeafObject[] leafs = filesTreeProvider.getAllLeafsOfDirectory(directoryNode);  
     for( int i=0; i < leafs.length; i++ )            
      {
        leafVector.addElement(leafs[i]);
        filenamesTextList.append( leafs[i].getName() + "\n" );
      }
     int[] foundPositions = SearchMethods.SearchTextOccurences( searchText,
                                                                doCaseSensitiveSearch,
                                                                doWholeWordsSearch,
                                                                doApproximateSearch,
                                                                approximateSearchMethodIndex,
                                                                approximateSearchTolerance,
                                                                filenamesTextList,
                                                                false );
     final Vector resultTargetVector = new Vector();
     int searchTextLength = searchText.length();
     for( int i=0; i < foundPositions.length; i++ )
      {
        int searchIndex = foundPositions[i];
        // The linenumber in the filenamesTextList gives the index of the leaf object
        // in the leafVector :
        int leafIndex = this.getLineNumberForPosition( searchIndex,filenamesTextList );
        if( leafIndex >= 0 )
         {
           EditableLeafObject editableLeafObject = (EditableLeafObject)leafVector.elementAt(leafIndex);
           // Note: By passing -1 as linenumber, the searchresults tree model will
           //       not create a filenode with a hit leaf, but only one
           //       file leaf (which just jumps to this file on doubleckick)
           SearchResultsUserObject entry = new SearchResultsUserObject( editableLeafObject,
                                                                        -1, // -> no hit leaf
                                                                        0,
                                                                        0 );
           resultTargetVector.addElement(entry);
         }
        // Size limitation : Break when we reach MaximumNumberOfHits added entries :
        if( resultTargetVector.size() >= MaximumNumberOfHits )
         {
           break;
         }
      } // for

     try
      {
        EventQueue.invokeAndWait( new Runnable()
         {
           public void run()
           {
             progressWindow.setVisible(false);
             progressWindow.dispose();
             // Add the search results to this tree ui :
             SearchResultsUserObject[] resultObjects = new SearchResultsUserObject[resultTargetVector.size()];
             resultTargetVector.copyInto(resultObjects);
             SearchResultsTreeModel model = (SearchResultsTreeModel)searchResultsTree.getModel();
             model.initializeTreeWith( resultObjects );
             // and if #hits > 0, make sure, the searchresultstree becomes visible,
             // by moving the splitpane a bit, if needed :
             projectFrame.popupSearchResultsTreePanel();
           }
         });
        Thread.sleep(33);
      }
     catch( Exception e9524876 ){}
     
     this.selectTabWithSearchResultsTree(searchResultsTree);

     // GC friendly: Do some cleanup, which make its work easier:
     leafVector.removeAllElements();
     leafVector = null;
   } // internal_searchDirectoryForFilename







 /**
  * Get the search results tree associated with the tab
  * with title searchedTabTitle. The tab is created, if it does
  * not exist.
  */
  private SearchResultsTree getSearchResultsTreeForTabWithTitle( String searchedTabTitle ) {
    SearchResultsTree searchResultsTree = null;
    // Get the existing tab with this name, create one otherwise.
    // setup the associated searchresults tree:
    for( int i=0; i < this.tabPane.getTabCount(); i++ ) {
      String tabTitle = this.tabPane.getTitleAt(i);
      if( tabTitle.equals(searchedTabTitle) ) {
        searchResultsTree = (SearchResultsTree)this.tabPane.getComponent(i);
        break;
      }
    }
    if( searchResultsTree == null ) { // does not exist, so create a new one in a new tab
      searchResultsTree = new SearchResultsTree( this.projectFrame,searchedTabTitle );
      // display the new tab:
      // Caution: Do not use tabPane.insertTab(), it's not working and
      // results in wrong tab and component associations. Use addTab: 
      this.tabPane.addTab( searchedTabTitle, searchResultsTree );
    }
    return searchResultsTree;
  }

  
  private void selectTabWithSearchResultsTree( SearchResultsTree searchResultsTree ) {
    for( int i=0; i < this.tabPane.getTabCount(); i++ ) {
      Component c = this.tabPane.getComponentAt(i);
      if( c == searchResultsTree ) {
        // Dont consume CPU power, when this tab alreay is selected:
        if( this.tabPane.getSelectedIndex() != i ) {
          // make the selection process Swing safe:
          if( EventQueue.isDispatchThread() ) {
            this.tabPane.setSelectedIndex(i);
          } else {
            final int iFinal = i;
            EventQueue.invokeLater( new Runnable() {
              public void run() {
                tabPane.setSelectedIndex(iFinal);
              }
            });
          }
        }
      }
    }
  }


  public void clear() {
    while( this.tabPane.getTabCount() > 0 ) {
      SearchResultsTree tree = (SearchResultsTree)this.tabPane.getComponent(0);
      tree.terminate();
      this.tabPane.removeTabAt(0);
    }
  }




} // SearchResultsPanel






  
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.