CodeCompletion.java :  » IDE » Schmortopf » Schmortopf » JavaSourceEditor » CodeCompletion » Java Open Source

Java Open Source » IDE » Schmortopf 
Schmortopf » Schmortopf » JavaSourceEditor » CodeCompletion » CodeCompletion.java
package Schmortopf.JavaSourceEditor.CodeCompletion;
                             
                                                         
  /**                                                     
   *  Created and used by EditorPanel.performCodeCompletion() .
   *                                     
   *                                                           
   *  This one extends from JPopupMenu and has the GUI included therefore.
   *                                
   *  An instance of this class is created in the method
   *  EditorPanel.performCodeCompletion().                                          
   *
   *  All calls are made OUTSIDE the eventdispatchthread, so this object
   *  must switch into the eventdispatch thread (or put tasks in its queue)
   *  when it performs Swing tasks.
   *            
   *  It tries to translate the passed basisIdentifier
   *  into a valid class identifier, shows its reachable member
   *  attributes and methods in a popup and inserts the selected
   *  name into the passed insertPosition of the current SourceEditorDocument.
   *                  
   */           
             
                    
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;       
import javax.swing.text.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import javax.swing.border.*;                                          
import javax.swing.tree.*;
import javax.swing.plaf.metal.*;
                                                
import Schmortopf.Main.IDE_ProjectFrameProvider;
import Schmortopf.FileStructure.*;
import Schmortopf.FileStructure.Descriptions.*;                                                    
import Schmortopf.JavaSourceEditor.*;                                                  
import Schmortopf.JavaSourceEditor.DocumentStyle.*;
import Schmortopf.Utility.gui.*;
import Schmortopf.Utility.IniFile.IniFile;
import Schmortopf.Utility.ThreadEngine.ThreadEngine;
import Schmortopf.FileComponents.View.SelfDrawingIcon;
import Schmortopf.ProjectFiles.SelectionTree.SelectionTreeIcon;
import Schmortopf.ProjectFiles.SelectionTree.SelectionTreeObject;
import Language.Language;                                                                  
import Shared.Logging.Log;                                  
                                                           

public class CodeCompletion extends JResizableUndecoratedFrame
{
                                         
  private final static String JavaCheckBoxSelectionIniFileKey = "CodeCompletion_JavaCheckBoxSelectionIniFileKey";
  private final static String RememberWindowSizeIniFileKey    = "CodeCompletion_RememberWindowSizeIniFileKey";
  private final static String DoShowOnlyMatchesIniFileKey     = "CodeCompletion_DoShowOnlyMatches";
                                      
  private final static String WindowWidthIniFileKey  = "CodeCompletion_WindowWidthIniFileKey";
  private final static String WindowHeightIniFileKey = "CodeCompletion_WindowHeightIniFileKey";
  private final static String WindowSplitLocationIniFileKey = "CodeCompletion_WindowSplitLocationIniFileKey";

  private static final SelfDrawingIcon OnIcon  = 
      new SelfDrawingIcon( Language.Translate("on") ,SelfDrawingIcon.ColorGreen);
  private static final SelfDrawingIcon OffIcon =
      new SelfDrawingIcon( Language.Translate("off") ,SelfDrawingIcon.ColorRed );
                      
  private static final SelectionTreeIcon SelectedIcon = 
      new SelectionTreeIcon( SelectionTreeObject.StateIsSelected,false,
                             SelectionTreeObject.Accessibility_Neutral );
  private static final SelectionTreeIcon NotSelectedIcon = 
      new SelectionTreeIcon( SelectionTreeObject.StateIsHidden,false,
                             SelectionTreeObject.Accessibility_Neutral );

  private static final SelfDrawingIcon SearchIcon =
      new SelfDrawingIcon( Language.Translate("Search") ,SelfDrawingIcon.ColorBlue);

  private static final SelfDrawingIcon JumpIcon =
      new SelfDrawingIcon( Language.Translate("Jump") ,SelfDrawingIcon.ColorGreen );

  private EditorPanel editorPanel;
  private FileStructureDescription currentlyEditedFSD;
  private FileStructureDescriptionManager fileStructureDescriptionManager;
  private IDE_ProjectFrameProvider projectFrame;
  private IniFile iniFile;

  private final String basisIdentifier;
  private final int insertPosition;

  final Point insertionPoint; // in the editorPanel coordsystem

  private CodeCompletion thisCodeCompletion;
                                       

  private JPanel splitWrapPanel;
  private JSplitPane splitPane;
  private JPanel mainPanel;
  private int originalDividerSize = 10;
  private JList entryList = null; // Contains the cc entries      
                    
  private boolean terminateHasBeenCalled = false;
                          
  private boolean doShowOnlyMatches = false; // Used in the method/attribute cc window
                                             // Loaded from the inifile
                                            
  // Tracks user inputs into the editor while this window is displayed.
  private final StringBuffer stringBuffer = new StringBuffer();
               
               
 /**
  *  Create the CodeCompletion popup with entries for the
  *  passed basisIdentifier (if one can translate it into a valid
  *  class identifier). The selection then is inserted at the passed
  *  insertPosition.
  *                     
  *  Note: The constructor is designed to be called from OUTSIDE
  *        the eventdispatch thread.
  */
  public CodeCompletion( final String basisIdentifier,
                         final int insertPosition,
                         final Point insertionPoint,
                         final EditorPanel editorPanel,
                         final FileStructureDescription currentlyEditedFSD,
                         final FileStructureDescriptionManager fileStructureDescriptionManager,
                         final IDE_ProjectFrameProvider projectFrame,
                         final IniFile iniFile )
  {
    super();
    // String title, boolean resizable, boolean closable,
    // boolean maximizable, boolean iconifiable
    this.basisIdentifier = basisIdentifier;
    this.insertPosition  = insertPosition;
    this.insertionPoint = insertionPoint;
    this.editorPanel = editorPanel;
    this.currentlyEditedFSD = currentlyEditedFSD;
    this.fileStructureDescriptionManager = fileStructureDescriptionManager;
    this.projectFrame = projectFrame;
    this.iniFile = iniFile;
    this.thisCodeCompletion = this;
    this.doShowOnlyMatches = this.iniFile.getBooleanValue(DoShowOnlyMatchesIniFileKey,false);
  } // Constructor

        








 /**
  *  The only public method, which performs the search using the
  *  parameters passed to the constructor.                                                     
  *
  *  The triggerCharacter = "." or "(" also is passed to this method. If it's
  *  a point or a space, either the method/attribute or the import CodeCompletion
  *  starts up, otherwise
  *  if its an opening bracket, the parameter CodeCompletion starts up.
  *
  *  Note: This is called from OUTSIDE the eventdispatch thread.
  */
  public void performFSDSearch( final char triggerCharacter,
                                final int caretLineNumber    )
  {                                              
    //Log.Info("called for basisIdentifier = " +
    //         this.basisIdentifier + "  with length= " + this.basisIdentifier.length() +
    //         "  and trigger=" + triggerCharacter );
    //long startTime = System.currentTimeMillis();

    if( this.currentlyEditedFSD == null )
     {   
       Log.Error("Designerror: currentlyEditedFSD is null. Returning.");
       return;
     }
    if( this.basisIdentifier.length() > 0 )
     {
       // Choose the CC mode depending on the trigger character :
       if( ( triggerCharacter == '.' ) ||   // [ point or space]
           ( triggerCharacter == ' ' )    ) // -> start the method/attributes or import CC :
        {
                 
          //ystem.out.println("CodeCompletion.performFSDSearch() started for trigger = space or point");

          // Conditions for one of the two possibilities :
          //
          // First we get the linenumber of the class declaration.
          // (= the line containing public class myClass extends .. or so )
          // an compare it with the current linenumber of the caret ( = the cursor).
          //
          // Case A )
          // The cursor is ABOVE the class declaration line, OR
          // a class declaration doesn't exist yet in the editedFSD, cause
          // the programmer has not written one yet.
          // -> In this case, only the import CC can make sense.
          //
          // Case B )
          // The class declaration line DOES exist in the edited FSD AND
          // the cursor is on the class declaration line or below.
          // -> start the method/attribute CC.
          //
          // Do that :
          final int classDeclarationLine = this.currentlyEditedFSD.className.startLine;
                                 
          //ystem.out.println("CodeCompletion.performFSDSearch(): classDeclarationLine= " + classDeclarationLine +
          //                   "  and caretLineNumber= " + caretLineNumber);

          if(  ( classDeclarationLine == -1 ) ||  // -> doesn't exist yet
               ( caretLineNumber < classDeclarationLine ) )
           {
              // Import CC
              // See, if the line contains a static import statement so far:
              String lineText = this.editorPanel.getEditor().getLineWithNumber(caretLineNumber);
              // 1.5 static import extension recognition:
              boolean isStaticImport = (lineText.indexOf(" static") >= 0 );
              // import CC :
              final CodeCompletionImportSearch codeCompletionImportSearch =
                    new CodeCompletionImportSearch( triggerCharacter,
                                                    isStaticImport,
                                                    this.basisIdentifier,
                                                    this.insertPosition,
                                                    this.editorPanel,
                                                    this.currentlyEditedFSD,
                                                    this.fileStructureDescriptionManager );
              final StringListEntry[] entryArray = codeCompletionImportSearch.performSearch(caretLineNumber);
              if( entryArray != null )
               {
                if( entryArray.length > 0 )
                 {
                  // Show the method/attribute CodeCompletion popup :
                  this.showImportCodeCompletionPopup(entryArray);
                 }
               }
           }
          else
           {
              // Method/attribute CC :
              final CodeCompletionSearch codeCompletionSearch =
                    new CodeCompletionSearch( this.basisIdentifier,
                                              this.insertPosition,
                                              this.editorPanel,
                                              this.currentlyEditedFSD,
                                              this.fileStructureDescriptionManager );
              final CodeCompletionListEntry[] codeCompletionListEntryArray = 
                    codeCompletionSearch.performSearch( caretLineNumber );
              if( codeCompletionListEntryArray != null )
               {
                if( codeCompletionListEntryArray.length > 0 )
                 {
                  // Show the method/attribute CodeCompletion popup.
                  // Use the classname of the class associated with the found fsd as title :
                  this.showCodeCompletionPopup( codeCompletionListEntryArray,
                                                codeCompletionSearch.getFoundIdentifierName() );
                 }
               }
              // We **must** release any updated transient fields now:
              codeCompletionSearch.freeAllTransientFields();
           } // else
        }
       else // it should be a "(" sign -> parameter CC :
        {                                                        

          //ystem.out.println("CodeCompletion.performFSDSearch() started for trigger = (");

          final CodeCompletionParameterSearch codeCompletionParameterSearch =
                new CodeCompletionParameterSearch( this.basisIdentifier,
                                                   this.insertPosition,
                                                   this.editorPanel,
                                                   this.currentlyEditedFSD,
                                                   this.fileStructureDescriptionManager );
          final CodeCompletionListEntry[] codeCompletionListEntryArray = codeCompletionParameterSearch.performSearch(caretLineNumber);
          if( codeCompletionListEntryArray != null )
           {
            if( codeCompletionListEntryArray.length > 0 )
             {                                                            
              // Show the Parameter CodeCompletion popup :
              this.showParameterCodeCompletionPopup( codeCompletionListEntryArray,
                                                     codeCompletionParameterSearch.getFoundIdentifierName() );
             }
           }
        }
     } // if
    //long elapsedTime = System.currentTimeMillis() - startTime;
    //Log.Info("CodeCompletion.performFSDSearch() ends. Elapsed time [ms] = " +
    //         elapsedTime );
  } // performFSDSearch






 /**
  *  Shows the method/attribute CodeCompletion popup. Swing-Thread-Safe.
  */                           
  private void showCodeCompletionPopup( final CodeCompletionListEntry[] codeCompletionListEntryArray,
                                        final String popupTitle )
  {
    // Only show it, if we have some items to display at all:
    if( codeCompletionListEntryArray.length > 0 )
     {
       final CodeCompletionListModel listModel =
         new CodeCompletionListModel( codeCompletionListEntryArray,
                                      this.fileStructureDescriptionManager );
       listModel.setShowOnlyMatches( this.doShowOnlyMatches ); // Set the display mode
       this.entryList = new JList(listModel);
       this.entryList.setCellRenderer( new CodeCompletionListCellRenderer() );
       // Keypress reaction: forward letters and numbers,
       // close on return or other keys :
       this.entryList.addKeyListener( new KeyAdapter()
        { 
          public void keyTyped(KeyEvent e)
          {
            final char ch = e.getKeyChar();
            final int charValue = (int)ch;

            //ystem.out.println(" ch = " + ch );
            //ystem.out.println(" charValue = " + charValue );
            //ystem.out.println(" keycode = " + e.getKeyCode() );            

            // Temporary: ctrl and alt keys are not handled for now.
            //            The problem additionally is, that the fsdupdater starts
            //            and produces a null fsd, if we process such events here.
            //            Producing a null fsd can have serious effects for the
            //            project and dependency calculations.
            //            Also the keycode only is available in keyPressed or
            //            keyReleased methods [gives some troubles & requires win+linux tests]
            if( e.isAltDown() || e.isControlDown() )                                              
             {       
               //ystem.out.println("modifier ctrl(alt down");                 
               return;
             }

            if( charValue == 8 ) // backspace was pressed
             {
               if( stringBuffer.length() > 0 )
                {
                 try
                  {
                    // remove the old stringbuffer from the editor :
                    editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                    // update the stringBuffer and the popup selection :
                    stringBuffer.setLength(  stringBuffer.length()-1 );
                    selectBestMatchingEntry( entryList,listModel,stringBuffer.toString() );
                    // insert the new stringbuffer content :
                    final Style style = StylesFactory.GetEditorTextStyle();
                    editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                  }
                 catch( Exception badloc3454 )
                  {
                    badloc3454.printStackTrace();
                  }
                }
               else
                {
                  // Remove the point character :
                  try
                   {
                     editorPanel.getEditor().getDocument().remove(insertPosition-1,1 );
                   }
                  catch( Exception e234876 ){}
                  // and just close the CC view :
                  if( ( isVisible() ) && (thisCodeCompletion != null ) )
                   {
                     setVisible(false);
                     terminate();
                   }
                } // else
             }
            else // if Return (CR of LF) was pressed, append the current selection and close it :
            if( ( charValue == 13 ) || ( charValue == 10 ) )
             {
               try
                {
                  // First remove the current buffer content, if any is there :
                  if( stringBuffer.length() > 0 )
                   {
                     // remove the old stringbuffer from the editor :
                     editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                     stringBuffer.setLength(0);
                   }
                  // Then take the current selection and append this one :
                  final int selectedIndex = entryList.getSelectedIndex();
                  if( selectedIndex >= 0 )
                   {
                    final CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)entryList.getModel().getElementAt( selectedIndex );
                    // and run it :
                    selectedEntry.run();
                   }
                }
               catch( Exception badloc6354 )
                {
                  badloc6354.printStackTrace();
                }
               // And close it :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  setVisible(false);
                  terminate();
                }
             }
            else // Escape was pressed: Close it :
            if( charValue == 27 )
             {
               // just close it :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  setVisible(false);
                  terminate();
                }
             }
            else
             {
               if( stringBuffer.length() < 1024 )
                {
                 // If the typed character has not been a java-identifier-character,
                 // close the popup :
                 if( Character.isJavaIdentifierPart(ch)  )
                  {
                    try
                     {
                       // update the stringBuffer and the popup selection :
                       stringBuffer.append(ch);
                       selectBestMatchingEntry( entryList,listModel,stringBuffer.toString() );
                       // insert the new character into the document too :
                       final Style style = StylesFactory.GetEditorTextStyle();
                       editorPanel.getEditor().getDocument().insertString(insertPosition + stringBuffer.length()-1,""+ch,style );
                     }
                    catch( Exception badloc12376 )
                     {
                       badloc12376.printStackTrace();
                     }
                  }
                 else
                  {
                    // If the typed character has not been a java-identifier-character,
                    // close the popup :
                    if( ( isVisible() ) && (thisCodeCompletion != null ) )
                     {
                       setVisible(false); // clear the way for a possible follower cc
                       try
                        {      
                          // update the stringBuffer and the popup selection :
                          stringBuffer.append(ch);
                          // insert the new character into the document too :
                          final Style style = StylesFactory.GetEditorTextStyle();
                          editorPanel.getEditor().getDocument().insertString(insertPosition + stringBuffer.length()-1,""+ch,style );
                        }
                       catch( Exception badloc12376 )
                        {
                          badloc12376.printStackTrace();
                        }
                       terminate();
                     }
                  }
                }
             }
          } // keyTyped
        }); // KeyAdapter

       // Select and close on double clicks :
       this.entryList.addMouseListener( new MouseAdapter()
        {
          public void mouseClicked( MouseEvent e )
          {
            if( e.getClickCount() > 1 ) // double click required
             {
               final int selectedIndex = entryList.getSelectedIndex();
               if( selectedIndex >= 0 )
                {
                  final CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)entryList.getModel().getElementAt( selectedIndex );
                  selectedEntry.run();
                  // Remove all - give the GC a better chance :
                  if( ( isVisible() ) && (thisCodeCompletion != null ) )
                   {
                     setVisible(false);
                     terminate();
                   }                          
                }
             }
          }
        });                           
                                  
       // close it, when it looses the focus :
       this.entryList.addFocusListener( new FocusAdapter()
        {
          public void focusLost( FocusEvent e )
          {                 
            // Remove all - give the GC a better chance :
            if( ( isVisible() ) && (thisCodeCompletion != null ) )
             {
               setVisible(false);
               terminate();
             }
          }           
        });
       // The list is complete including attached listeners, now show it.
       // JavaDoc available -> last parm set.
       this.showPopup( this.entryList,listModel,popupTitle,true,true,true );
     } // if
  } // showCodeCompletionPopup


                                     
                                                     
                       
  private void selectBestMatchingEntry( final JList list,
                                        final CodeCompletionListModel listModel,
                                        final String compareBasis )
  {                                                            
   // Update the ccText always. It wouldn't be required when doShowOnlyMatches is clear,
   // but it's required when the user changes between the two modes for having       
   // immediate update, so update it always:                                                             
   listModel.setCurrentccText( compareBasis );
   // update the model, which has an effect only, if its memberattribute
   // doShowOnlyMatches is set:
   if( listModel.getShowOnlyMatches() )
    {
      listModel.rebuildList();
    }
   if( compareBasis.length() > 0 )
    {
      int indexForSelection = 0;
      while( indexForSelection < listModel.getSize() )
       {                                                        
         final CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)listModel.getElementAt( indexForSelection );
         final String compareString = selectedEntry.getComparatorString();
         if( compareBasis.compareToIgnoreCase(compareString) <= 0 )
          {
            break; // found the best matching entry
          }
         else
          {
            indexForSelection++;
          }
       }
      // select and scroll to the selected line :
      selectAndScrollToListIndex( list, indexForSelection );
    }            
  } // selectBestMatchingEntry
                   
            

 /**            
  *  Helps the GC be releasing associations.
  */
  private void terminate()
  {
    if( !this.terminateHasBeenCalled )
     {
       this.terminateHasBeenCalled = true;
       // This CodeCompletion object runs in a ThreadEngine thread,
       // so we are safe to free the member attributes, if we delay
       // it in a ThreadEngine Thread :
       Runnable terminatorRunnable = new Runnable()
        {
          public void run()
          {
            EventQueue.invokeLater( new Runnable()
             {
               public void run()
               {
                 internal_delayed_terminate();
               }
             });             
          }                  
        };
       ThreadEngine.getInstance().addRunnable(terminatorRunnable,"CC TerminatorRunnable");   
     }
  } // terminate




  private void internal_delayed_terminate()
  {
    getContentPane().removeAll();
    thisCodeCompletion = null;
    editorPanel = null;
    currentlyEditedFSD = null;
    fileStructureDescriptionManager = null;
    projectFrame = null;
    iniFile = null;
    splitWrapPanel = null;
    splitPane = null;
    mainPanel = null;
    this.dispose(); // Linux requirement: Kill it completely.
  } // internal_terminate
    




 /**
  *  Shows the Import CodeCompletion popup. Swing-Thread-Safe.
  */
  private void showImportCodeCompletionPopup( final StringListEntry[] stringListEntryArray )
  {                                 
    // Only show it, if we have some items to display at all:
    if( stringListEntryArray.length > 0 )
     {                                            
       final StringListModel listModel = new StringListModel(stringListEntryArray);
       this.entryList = new JList(listModel);
       this.entryList.setCellRenderer( new StringListCellRenderer() );
       // Keypress reaction: forward letters and numbers,
       // close on return or other keys :
       this.entryList.addKeyListener( new KeyAdapter()
        {
            
          public void keyTyped(KeyEvent e)
          {
            final char ch = e.getKeyChar();
            final int charValue = (int)ch;
            if( charValue == 8  ) // backspace was pressed
             {
               if( stringBuffer.length() > 0 )
                {
                 try
                  {
                    // remove the old stringbuffer from the editor :
                    editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                    // update the stringBuffer and the popup selection :
                    stringBuffer.setLength(  stringBuffer.length()-1 );
                    local_selectBestMatchingEntry();
                    // insert the new stringbuffer content :
                    final Style style = StylesFactory.GetEditorTextStyle();
                    editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                  }
                 catch( Exception badloc3454 )
                  {
                    badloc3454.printStackTrace();
                  }
                }
               else // backspace when already empty -> close it
                {
                  // Remove the point (or space) character :
                  try
                   {
                     editorPanel.getEditor().getDocument().remove(insertPosition-1,1 );
                   }
                  catch( Exception e234876 ){}
                  if( ( isVisible() ) && (thisCodeCompletion != null ) )
                   {
                     setVisible(false);
                     terminate();
                   }            
                }
             }
            else // escape was pressed, close it :
            if( charValue == 27 )
             {
               // just close it :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  setVisible(false);
                  terminate();
                }            
             }
            else // if Return (CR of LF) was pressed, append the current selection and close it :
            if( ( charValue == 13 ) || ( charValue == 10 ) )
             {
               try
                {
                  // First remove the current buffer content, if any is there :
                  if( stringBuffer.length() > 0 )
                   {
                     // remove the old stringbuffer from the editor :
                     editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                     stringBuffer.setLength(0);
                   }
                  // Then take the current selection and append this one :
                  final int selectedIndex = entryList.getSelectedIndex();
                  if( selectedIndex >= 0 )
                   {
                    final StringListEntry selectedEntry = (StringListEntry)entryList.getModel().getElementAt( selectedIndex );
                    // Insert the comparatorstring of the selected entry.
                    // If it's a leaf, we can add a ";" sign, otherwise
                    // we can add a point, which then triggers the next import CC.
                    // Exception: After the 1.5 static import, we insert a new space instead of a point.
                    String insertionString = null;
                    if( selectedEntry.is_LeafContent )
                     {
                       insertionString = selectedEntry.getComparatorString() + ";";
                     } 
                    else
                     {
                       if( selectedEntry.getComparatorString().equals("static") )
                        {
                          insertionString = selectedEntry.getComparatorString() + " ";
                        }
                       else
                        {
                          insertionString = selectedEntry.getComparatorString() + ".";
                        }
                     }
                    // First close it :
                    if( ( isVisible() ) && (thisCodeCompletion != null ) )
                     {
                       setVisible(false);
                     }
                    // then insert the text, which again can force the popup to be displayed,
                    // if f.ex. it ends with a point:             
                    final Style style = StylesFactory.GetEditorTextStyle();
                    editorPanel.getEditor().getDocument().insertString(insertPosition,insertionString,style );
                   }
                }
               catch( Exception badloc6354 )
                {
                  badloc6354.printStackTrace();
                }
               // Close it :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  setVisible(false);
                  terminate();
                }            
             }
            else
             {
               if( stringBuffer.length() < 1024 )
                {
                 // If the typed character has not been a java-identifier-character,
                 // close the popup :
                 if( Character.isJavaIdentifierPart(ch)  )
                  {
                    try
                     {
                       // remove the old stringbuffer from the editor :
                       editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                       // update the stringBuffer and the popup selection :
                       stringBuffer.append(ch);
                       local_selectBestMatchingEntry();
                       // insert the new stringbuffer content :
                       final Style style = StylesFactory.GetEditorTextStyle();
                       editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                     }
                    catch( Exception badloc12376 )
                     {
                       badloc12376.printStackTrace();
                     }
                  }
                 else // If the typed character has not been a java-identifier-character,close the popup :
                  {   
                     if( ( isVisible() ) && (thisCodeCompletion != null ) )
                     {
                       setVisible(false); // first close the cc, as a follower could come up
                       try
                        {
                           // remove the old stringbuffer from the editor :
                           editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                           // update the stringBuffer and the popup selection :
                           stringBuffer.append(ch);
                           // insert the new stringbuffer content :
                           final Style style = StylesFactory.GetEditorTextStyle();
                           editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                        }
                       catch( Exception badloc12376 )
                        {
                          badloc12376.printStackTrace();
                        }
                       terminate();
                     }      
                  }
                }
             }
          } // keyTyped

          private void local_selectBestMatchingEntry()
          {
           if( stringBuffer.length() > 0 )
            {
              final String compareBasis = stringBuffer.toString();
              int indexForSelection = 0;
              while( indexForSelection < entryList.getModel().getSize() )
               {
                 final StringListEntry selectedEntry = (StringListEntry)entryList.getModel().getElementAt( indexForSelection );
                 final String compareString = selectedEntry.getComparatorString();
                 if( compareBasis.compareToIgnoreCase(compareString) <= 0 )
                  {
                    break; // found the best matching entry
                  }
                 else
                  {
                    indexForSelection++;
                  }
               }
              // select and scroll to the selected line :
              selectAndScrollToListIndex( entryList, indexForSelection );
            }
          } // selectBestMatchingEntry

        }); // KeyAdapter

       // Select and close on double clicks :
       this.entryList.addMouseListener( new MouseAdapter()
        {
          public void mouseClicked( MouseEvent e )
          {
            if( e.getClickCount() > 1 ) // double click required
             {
               final int selectedIndex = entryList.getSelectedIndex();
               if( selectedIndex >= 0 )    
                {
                  final StringListEntry selectedEntry = (StringListEntry)entryList.getModel().getElementAt( selectedIndex );
                  selectedEntry.run();
                  // Remove all - give the GC a better chance :
                  if( ( isVisible() ) && (thisCodeCompletion != null ) )
                   {
                     setVisible(false);
                     terminate();
                   }            
                }
             }
          }
        });
                                                                              
       // close it, when it looses the focus :
       this.entryList.addFocusListener( new FocusAdapter()
        {
          public void focusLost( FocusEvent e )
          {
            // Remove all - give the GC a better chance :
            if( ( isVisible() ) && (thisCodeCompletion != null ) )
             {
               setVisible(false);
               terminate();
             }            
          }
        });
       // The list is complete including attached listeners, now show it.
       // No JavaDoc available -> last parm clear.
       this.showPopup( entryList,listModel,"",false,false,false );
     } // if
  } // showImportCodeCompletionPopup

                                 


                                           

 /**
  *  Shows the Parameter CodeCompletion popup. Swing-Thread-Safe.
  */
  private void showParameterCodeCompletionPopup( final CodeCompletionListEntry[] codeCompletionListEntryArray,
                                                 final String popupTitle )
  {
    // Only show it, if we have some items to display :
    if( codeCompletionListEntryArray.length > 0 )
     {
       final CodeCompletionListModel listModel = new CodeCompletionListModel(codeCompletionListEntryArray,this.fileStructureDescriptionManager);
       listModel.setShowOnlyMatches( false ); // not supported for parameter cc, only for method/attribute cc
       this.entryList = new JList(listModel);
       this.entryList.setCellRenderer( new CodeCompletionListCellRenderer() );
       // Keypress reaction: forward letters and numbers,
       // close on return or other keys :
       this.entryList.addKeyListener( new KeyAdapter()
        {
          public void keyTyped(KeyEvent e)
          {
            final char ch = e.getKeyChar();
            final int charValue = (int)ch;
            if( charValue == 8  ) // backspace was pressed
             {
               if( stringBuffer.length() > 0 )
                {
                 try
                  {
                    // remove the old stringbuffer from the editor :
                    editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                    // update the stringBuffer and the popup selection :
                    stringBuffer.setLength(  stringBuffer.length()-1 );
                    local_selectBestMatchingEntry();
                    // insert the new stringbuffer content :
                    final Style style = StylesFactory.GetEditorTextStyle();
                    editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                  }
                 catch( Exception badloc3454 )
                  {
                    badloc3454.printStackTrace();
                  }
                }
               else // backspace when already empty -> close it
                {
                  if( ( isVisible() ) && (thisCodeCompletion != null ) )
                   {
                     setVisible(false); // Clear the way for a possible follower cc
                     // Remove the point character :
                     try
                      {
                        editorPanel.getEditor().getDocument().remove(insertPosition-1,1 );
                      }
                     catch( Exception e234876 ){}
                     terminate();
                   }
                }
             }
            else // if escape, return or another lowvalue character was pressed, close it :
            if( charValue < 32 )
             {
               // just close it :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  setVisible(false);
                  terminate();
                }
             }
            else
            if( ( ch == ')'  ) || ( ch == '.' ) ) // closing bracket or point was pressed -> close 
             {
               // Close it, but append the bracket too :
               if( ( isVisible() ) && (thisCodeCompletion != null ) )
                {
                  try
                   {
                     setVisible(false); // Clear the way for a possible follower cc frame.
                     // remove the old stringbuffer from the editor :
                     editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                     // update the stringBuffer and the popup selection :
                     stringBuffer.append(ch);
                     // insert the new stringbuffer content :
                     final Style style = StylesFactory.GetEditorTextStyle();
                     editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                   }
                  catch( Exception badloc12376 )
                   {
                     badloc12376.printStackTrace();
                   }
                  terminate();
                }
             }
            else
             {
               if( stringBuffer.length() < 1024 )
                {
                 try
                  {
                    // remove the old stringbuffer from the editor :
                    editorPanel.getEditor().getDocument().remove(insertPosition,stringBuffer.length() );
                    // update the stringBuffer and the popup selection :
                    local_selectBestMatchingEntry();
                    stringBuffer.append(ch);
                    // insert the new stringbuffer content :
                    final Style style = StylesFactory.GetEditorTextStyle();
                    editorPanel.getEditor().getDocument().insertString(insertPosition,stringBuffer.toString(),style );
                  }
                 catch( Exception badloc12376 )
                  {
                    badloc12376.printStackTrace();
                  }
                }
             }
          } // keyTyped



          private void local_selectBestMatchingEntry()
          {
           if( stringBuffer.length() > 0 )
            {
              final String compareBasis = stringBuffer.toString();
              int indexForSelection = 0;
              while( indexForSelection < entryList.getModel().getSize() )
               {
                 final CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)entryList.getModel().getElementAt( indexForSelection );
                 final String compareString = selectedEntry.getComparatorString();
                 if( compareBasis.compareToIgnoreCase(compareString) <= 0 )
                  {
                    break; // found the best matching entry
                  }
                 else
                  {
                    indexForSelection++;
                  }
               }
              // select and scroll to the selected line :
              selectAndScrollToListIndex( entryList, indexForSelection );
            }
          } // selectBestMatchingEntry

        }); // KeyAdapter

       // close it, when it looses the focus :
       this.entryList.addFocusListener( new FocusAdapter()
        {
          public void focusLost( FocusEvent e )
          {
            // Remove all - give the GC a better chance :
            if( ( isVisible() ) && (thisCodeCompletion != null ) )
             {
               setVisible(false);
               terminate();
             }            
          }
        });
       // The list is complete including attached listeners, now show it :
       // JavaDoc available -> last parm set.
       this.showPopup( this.entryList,listModel,popupTitle,true,false,false );
     } // if
  } // showParameterCodeCompletionPopup


                         



                         

 /**
  *  This is called from showCodeCompletionPopup and from
  *  showParameterCodeCompletionPopup, after the list has been
  *  created with all needed contents and listeners.
  */
  private void showPopup( final JList list,
                          final ListModel listModel,
                          final String popupTitle,
                          final boolean javaDocIsAvailable,
                          final boolean isJumpSupported,
                          final boolean isMethodAttributeCC )
  {    
     // Change the coordinatesystem from editorpanel to screen :
     Point globalPoint = new Point( insertionPoint );
     SwingUtilities.convertPointToScreen(globalPoint,editorPanel);

     final Font treeFont = UIManager.getFont("Tree.font");
     // treeFont is used for the labels with selfdrawing items,
     // cause these also use the treefont.
     final int gap = treeFont.getSize();

     // preferred location:
     int xp = globalPoint.x - gap;
     int yp = globalPoint.y + 2*gap;

     this.splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );

     this.originalDividerSize = this.splitPane.getDividerSize();
     // The dividersize is set to zero, while the javadoc is turned off.

     this.mainPanel = new JPanel( new BorderLayout(0,0) );
     this.mainPanel.setMinimumSize( new Dimension(36*gap,20*gap) );

     this.splitWrapPanel = new JPanel( new BorderLayout(0,0) );
     this.splitWrapPanel.add( this.splitPane, BorderLayout.CENTER );

     this.getContentPane().setLayout( new BorderLayout(0,0) );
     this.getContentPane().add( this.splitWrapPanel, BorderLayout.CENTER );

     this.splitPane.setLeftComponent(mainPanel);

     final int bw = 1+gap/3;
     final Border inb  = BorderFactory.createEmptyBorder(bw,bw,bw,bw);
     final Border outb = BorderFactory.createRaisedBevelBorder();
     this.splitWrapPanel.setBorder( BorderFactory.createCompoundBorder(outb, inb) );
     // Note: This border is very important, otherwise the resize methods
     // of the parentobject (JResizableWindow) wouldn't work.
     // JResizableWindow will control the mainpanel's cursor.

     // If a title has been passed, display it at the top, and also add the top switches:
     if( popupTitle != null )
      {
        if( popupTitle.length() > 0 )
         {
           JPanel titlePanel = new JPanel( new BorderLayout(gap/2,0) );

           // The title:
           JContrastLabel titleLabel = new JContrastLabel("  " + popupTitle );
           titleLabel.setFont(treeFont);

           // The search field ( added only for the attribute/method cc )
           if( isMethodAttributeCC )
            {
               final CodeCompletionListModel ccListModel = (CodeCompletionListModel)listModel;
               final JContrastLabel showMatchesLabel =
                 new JContrastLabel( Language.Translate("Matches only") );
               showMatchesLabel.setFont(treeFont);
               showMatchesLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
               showMatchesLabel.setIcon( (this.doShowOnlyMatches) ? OnIcon : OffIcon );
               // dynamic behaviour :
               showMatchesLabel.addMouseListener( new MouseAdapter()
                {
                  public void mouseReleased( MouseEvent e )
                  {
                    // toggle
                    if(showMatchesLabel.getIcon() == OnIcon)
                     {
                       // turn it off:
                       showMatchesLabel.setIcon( OffIcon );
                       ccListModel.setShowOnlyMatches(false);
                       selectBestMatchingEntry( list,ccListModel,stringBuffer.toString() );
                       doShowOnlyMatches = false;
                       iniFile.setBooleanValue(DoShowOnlyMatchesIniFileKey,false);
                     }
                    else
                     {
                       showMatchesLabel.setIcon( OnIcon );
                       ccListModel.setShowOnlyMatches(true);
                       selectBestMatchingEntry( list,ccListModel,stringBuffer.toString() );
                       doShowOnlyMatches = true;
                       iniFile.setBooleanValue(DoShowOnlyMatchesIniFileKey,true);
                     }
                  }
                });
               JPanel titleCombiPanel = new JPanel( new BorderLayout(0,0) );
               titleCombiPanel.add(showMatchesLabel, BorderLayout.SOUTH );
               // Add the titleLabel on the top, and the search part below it:
               titleCombiPanel.add( titleLabel, BorderLayout.CENTER );
               // Add that combi panel:
               titlePanel.add( titleCombiPanel, BorderLayout.WEST );
            } // if
           else
            {
              // Only add the titleLabel:
              titlePanel.add(titleLabel, BorderLayout.WEST);
            }
           // Add them:
           // For classmethod and parameter cc, which have a CodeCompletionListModel,
           // we can display attribute and method on/off switches :
           if( listModel instanceof CodeCompletionListModel )
            {
               final CodeCompletionListModel ccListModel = (CodeCompletionListModel)listModel;

               JPanel rightTitlePanel = new JPanel( new BorderLayout(gap/2,0) );
               JPanel left_RightTitlePanel = new JPanel( new BorderLayout(0,0) );
               JPanel right_RightTitlePanel = new JPanel( new BorderLayout(0,0) );
               rightTitlePanel.add( left_RightTitlePanel, BorderLayout.CENTER );
               rightTitlePanel.add( right_RightTitlePanel, BorderLayout.EAST  );
               titlePanel.add( rightTitlePanel, BorderLayout.EAST );

               final JContrastLabel showAttributesLabel = new JContrastLabel( Language.Translate("Attributes") + " " );
               showAttributesLabel.setFont(treeFont);
               showAttributesLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
               showAttributesLabel.setIcon( OnIcon );
               // dynamic behaviour :
               showAttributesLabel.addMouseListener( new MouseAdapter()
                {
                  public void mouseReleased( MouseEvent e )
                  {
                    // toggle
                    if(showAttributesLabel.getIcon() == OnIcon)
                     {
                       // turn it off:
                       showAttributesLabel.setIcon( OffIcon );
                       ccListModel.setShowAttributes( false );
                     }
                    else
                     {
                       showAttributesLabel.setIcon( OnIcon );
                       ccListModel.setShowAttributes( true );
                     }
                  }
                });
               left_RightTitlePanel.add( showAttributesLabel, BorderLayout.CENTER );

               final JContrastLabel showInheritedObjectsLabel = new JContrastLabel( Language.Translate("Inherited") + " " );
               showInheritedObjectsLabel.setFont(treeFont);
               showInheritedObjectsLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
               showInheritedObjectsLabel.setIcon( OnIcon );
               // dynamic behaviour :
               showInheritedObjectsLabel.addMouseListener( new MouseAdapter()
                {
                  public void mouseReleased( MouseEvent e )
                  {
                    // toggle
                    if(showInheritedObjectsLabel.getIcon() == OnIcon)
                     {
                       // turn it off:
                       showInheritedObjectsLabel.setIcon( OffIcon );
                       ccListModel.setShowInheritedObjects( false );
                     }
                    else
                     {
                       showInheritedObjectsLabel.setIcon( OnIcon );
                       ccListModel.setShowInheritedObjects( true );
                     }
                  }
                });
               left_RightTitlePanel.add( showInheritedObjectsLabel, BorderLayout.SOUTH );


               final JContrastLabel showMethodsLabel = new JContrastLabel( Language.Translate("Methods") + " " );
               showMethodsLabel.setFont(treeFont);
               showMethodsLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
               showMethodsLabel.setIcon( OnIcon );
               // dynamic behaviour :
               showMethodsLabel.addMouseListener( new MouseAdapter()
                {
                  public void mouseReleased( MouseEvent e )
                  {
                    // toggle
                    if(showMethodsLabel.getIcon() == OnIcon)
                     {
                       // turn it off:
                       showMethodsLabel.setIcon( OffIcon );
                       ccListModel.setShowMethods( false );
                     }
                    else
                     {
                       showMethodsLabel.setIcon( OnIcon );
                       ccListModel.setShowMethods( true );
                     }
                  }
                });
               right_RightTitlePanel.add( showMethodsLabel, BorderLayout.CENTER );


               final JContrastLabel showProjectOnlyLabel = new JContrastLabel( Language.Translate("Project Only") + " ");
               showProjectOnlyLabel.setFont(treeFont);
               showProjectOnlyLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
               showProjectOnlyLabel.setIcon( OffIcon );
               // dynamic behaviour :
               showProjectOnlyLabel.addMouseListener( new MouseAdapter()
                {
                  public void mouseReleased( MouseEvent e )
                  {
                    // toggle
                    if(showProjectOnlyLabel.getIcon() == OnIcon)
                     {
                       // turn it off:
                       showProjectOnlyLabel.setIcon( OffIcon );
                       ccListModel.setShowProjectObjectsOnly( false );
                     }
                    else
                     {
                       showProjectOnlyLabel.setIcon( OnIcon );
                       ccListModel.setShowProjectObjectsOnly( true );
                     }
                  }
                });
               right_RightTitlePanel.add( showProjectOnlyLabel, BorderLayout.SOUTH );

            } // if

           mainPanel.add( titlePanel, BorderLayout.NORTH );
         }
      }

     final JScrollPane scrollPane = new JScrollPane(list);
     scrollPane.setCursor( new Cursor( Cursor.DEFAULT_CURSOR) );
     mainPanel.add( scrollPane, BorderLayout.CENTER );

     JPanel buttonPanel = new JPanel( new BorderLayout(0,0) );
     mainPanel.add( buttonPanel, BorderLayout.SOUTH );

     JPanel jumpPanel = new JPanel( new BorderLayout(0,0) );
     jumpPanel.setBorder( BorderFactory.createEmptyBorder(0,0,0,0) );
     buttonPanel.add( jumpPanel, BorderLayout.NORTH );
     if( isJumpSupported )
      {
        final JContrastLabel jumpLabel = new JContrastLabel( Language.Translate("to the selected entry.") );
        jumpLabel.setFont(treeFont);
        jumpLabel.setIcon( JumpIcon );
        jumpLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
        // dynamic behaviour :
        jumpLabel.addMouseListener( new MouseAdapter()
         {
           public void mouseReleased( MouseEvent e )
           {
             Object selectedObject = list.getSelectedValue();
             if( selectedObject != null )
              {
                if( selectedObject instanceof CodeCompletionListEntry )
                 {
                   setVisible(false); // close this popup
                   // call freeMemory on the bottom of this block
                   CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)selectedObject;
                   if( selectedEntry.isMethodEntry() )
                    {
                      jumpToMethodInFile( selectedEntry.getMethodFSD(), selectedEntry.getParentFSD() );
                    }
                   else
                   if( selectedEntry.isFieldEntry() )
                    {
                      jumpToFieldInFile( selectedEntry.getFieldFSD(), selectedEntry.getParentFSD() );
                    }
                   else
                   if( selectedEntry.isStaticInnerClassEntry() )
                    {
                      jumpToStaticInnerClassInFile( selectedEntry.getStaticInnerClassFSD(), selectedEntry.getParentFSD() );
                    }
                   else
                    {
                      Log.Info("CC jumpLabel handler: neither method nor field");
                    }
                   terminate();
                 }
                else
                 {
                   Log.Error("CC jumpLabel handler: wrong instance: " +
                             selectedObject.getClass().getName() );
                 }
              }
             else
              {
                Log.Warn("CC jumpLabel handler: selectedObject is NULL");
              }
           }
         });
        jumpPanel.add( jumpLabel, BorderLayout.WEST );
      } // if jump is supported
                  
     boolean javaDocIsActive = this.iniFile.getBooleanValue(JavaCheckBoxSelectionIniFileKey,false);

     // Give the mainpanel a constant witdh (with regard to the current fontsize)
     // but make the height dependent from the number of entries
     // up to a certain limit :
     int popupVerticalCount = list.getModel().getSize();
     if( popupVerticalCount <  8 ) popupVerticalCount =  8;
     if( popupVerticalCount > 16 ) popupVerticalCount = 16;
     int horizontalSize = 36*gap;
     final int javaDocPanelHeight = 8 * gap;
     final int ccPanelHeight = 3*gap + (popupVerticalCount*5*gap)/4;
     int verticalSize = 0;
     if( javaDocIsActive && javaDocIsAvailable )
      {
        verticalSize = ccPanelHeight + javaDocPanelHeight;
        this.splitPane.setDividerSize(this.originalDividerSize);
      }
     else
      {
        verticalSize = ccPanelHeight;
        this.splitPane.setDividerSize(0);
      }
     final NonFocusBackgroundTextArea javaDocArea = new NonFocusBackgroundTextArea("");
     javaDocArea.setBorder( BorderFactory.createEmptyBorder(0,gap,0,gap) );
     // gives space on the sides without going outof sync with the background.
     javaDocArea.setEditable(false);
     javaDocArea.setRequestFocusEnabled(false);
     list.addListSelectionListener( new ListSelectionListener()
      {
        public void valueChanged(ListSelectionEvent e)
        {
          if( javaDocArea.isVisible() )
           {
             Object selectedObject = list.getSelectedValue();
             if( selectedObject != null )
              {
                if( selectedObject instanceof CodeCompletionListEntry )
                 {                                   
                   CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)selectedObject;
                   String javaDocText = selectedEntry.getJavaDoc();                          
                   javaDocArea.setText( javaDocText );
                   javaDocArea.setCaretPosition(0);                      
                 }
              }
           }
        }
      });


    final JContrastLabel javaDocSwitchLabel = new JContrastLabel( Language.Translate("Show Javadoc Comments") + " ");
    javaDocSwitchLabel.setFont(treeFont);
    javaDocSwitchLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
    if( javaDocIsActive )
        javaDocSwitchLabel.setIcon( OnIcon ); else
        javaDocSwitchLabel.setIcon( OffIcon);

    boolean rememberSize = this.iniFile.getBooleanValue(RememberWindowSizeIniFileKey,false);
    final JContrastLabel rememberSizeLabel = new JContrastLabel( Language.Translate("Remember Size") + " " );
    rememberSizeLabel.setFont(treeFont);
    rememberSizeLabel.setCursor( new Cursor( Cursor.HAND_CURSOR) );
    if( rememberSize )
        rememberSizeLabel.setIcon( OnIcon ); else
        rememberSizeLabel.setIcon( OffIcon);
    // dynamic behaviour :
    rememberSizeLabel.addMouseListener( new MouseAdapter()
     {
       public void mouseReleased( MouseEvent e )
       {
         // toggle
         if(rememberSizeLabel.getIcon() == OnIcon)
          {
            // turn it off:
            rememberSizeLabel.setIcon( OffIcon );
            iniFile.setBooleanValue(RememberWindowSizeIniFileKey,false);
          }
         else
          {
            rememberSizeLabel.setIcon( OnIcon );
            iniFile.setBooleanValue(RememberWindowSizeIniFileKey,true);
          }
       }
     });

    JPanel switchPanel = new JPanel( new BorderLayout(0,0) );
    switchPanel.add( javaDocSwitchLabel, BorderLayout.WEST );
    switchPanel.add( rememberSizeLabel, BorderLayout.EAST );
    switchPanel.setBorder( BorderFactory.createEmptyBorder(0,0,0,0) );
    buttonPanel.add( switchPanel, BorderLayout.CENTER );

     // Only add the javadoc subpanel, if JavaDoc also is available.
     // It is available for method/attribute CC, but not for import cc.
     if( javaDocIsAvailable )
      {
        JPanel javaDocPanel = new JPanel( new BorderLayout(0,0) );
        splitPane.setRightComponent(javaDocPanel);
        this.buildTheJavaDocPanel( javaDocPanel,gap,javaDocPanelHeight,horizontalSize,
                                   javaDocArea,list,javaDocIsActive,javaDocSwitchLabel );
      }

     // Set the mainpanels preferred size :
     splitPane.setDividerLocation(ccPanelHeight-gap*3);
     splitWrapPanel.setSize( new Dimension( horizontalSize,verticalSize ) );
     splitWrapPanel.setPreferredSize( new Dimension( horizontalSize,verticalSize ) );
     // and let Swing set all preferred sizes :
     this.pack();

     // Overwrite the default values by stored values,if the flag is set and
     // if values were found on the inifile too :
     if( rememberSize )
      {
        int ws = iniFile.getIntegerValue(WindowWidthIniFileKey,this.getSize().width);
        int hs = iniFile.getIntegerValue(WindowHeightIniFileKey,this.getSize().height);
        int sp = iniFile.getIntegerValue(WindowSplitLocationIniFileKey,this.splitPane.getDividerLocation());
        this.setSize(ws,hs);
        this.splitPane.setDividerLocation(sp);
        // and adjust the cachd values too (so that the location is set correctly below) :
        horizontalSize = ws;
        verticalSize   = hs;
      }
     // Set the location :
     // preferred would be (xp,yp), but if the JWindow would go
     // outside the screen, we have to choose an alternate location,
     // so test the location and change if needed :
     final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
     // vertical location :
     if( yp + verticalSize > screen.height )
      {
        // show it above the line instead :
        yp = globalPoint.y - verticalSize;
      }
     // horizontal location
     if( xp + horizontalSize + gap > screen.width )
      {
        // move it to the left :
        xp = screen.width - horizontalSize - gap;
      }
     // now set the location :
     setLocation(xp,yp);

     setVisible(true);
     list.setSelectedIndex(0);
     list.requestFocusInWindow(); // new, to be tried out

     /* temporarily outcommented ( time consumation? )
     list.requestDefaultFocus();
     list.requestFocus();
     */

  } // showPopup




 /**
  *  Overwritten for additionally storing state attributes
  *  when its made invisible.
  */
  public void setVisible( boolean state )
  {              
    if( !state )
     {                   
       if( iniFile != null )
        {
          if( iniFile.getBooleanValue(RememberWindowSizeIniFileKey,false) )
           {
             iniFile.setIntegerValue(WindowWidthIniFileKey,getSize().width );
             iniFile.setIntegerValue(WindowHeightIniFileKey,getSize().height );
             iniFile.setIntegerValue(WindowSplitLocationIniFileKey,splitPane.getDividerLocation() );
           }
        }
     }
    super.setVisible(state);
    if( state )
     {
       EventQueue.invokeLater( new Runnable()
        {
          public void run()
          {
            toFront();
          }
        });     
     }
    else
     {
       // This especially is required for JDK 1.4 or later, because in these
       // JVM's, the editor wouldn't get the focus back after the CodeCompletion
       // popup has been closed.
       if( editorPanel != null )
        {
          if( editorPanel.getEditor() != null )
           {
             editorPanel.getEditor().requestFocus();
             editorPanel.getEditor().setSelectionStart( editorPanel.getEditor().getCaretPosition() );
             editorPanel.getEditor().setSelectionEnd( editorPanel.getEditor().getCaretPosition() );
           }
        }
     }             
  } // setVisible





 /**
  *  Adds the panel, which contains the JavaDoc checkbox,
  *  and the JavaDoc content panel, if that checkbox is selected,
  *  and as long as it's selected.
  */
  private void buildTheJavaDocPanel( final JPanel basisPanel,
                                     final int fontSize,
                                     final int javaDocPanelHeight,
                                     final int horizontalSize,
                                     final JTextArea javaDocArea,
                                     final JList list,
                                     final boolean javaDocIsActive,
                                     final JLabel javaDocSwitchLabel )
  {
    final JFrame thisWindow = this;

    final Font treeFont = UIManager.getFont("Tree.font");
    // treeFont is used for the labels with selfdrawing items,
    // cause these also use the treefont.

    final JScrollPane javaDocScrollPane = new JScrollPane( javaDocArea );
    // Set the preferred size of the javaDoc scrollpane :
    // Same width like the mainpanel of the popup, 4 fontsizes height.
    // This size will be set by the pack() call of the caller.
    javaDocScrollPane.setPreferredSize( new Dimension( horizontalSize,javaDocPanelHeight ) );
    javaDocScrollPane.setRequestFocusEnabled(false);
    basisPanel.add( javaDocScrollPane, BorderLayout.CENTER );
    // Set visibility depending of the javaDocSwitchLabel state :
    javaDocScrollPane.setVisible( (javaDocSwitchLabel.getIcon() == OnIcon) );  // both containers must
    javaDocArea.setVisible( (javaDocSwitchLabel.getIcon() == OnIcon) );        // change visibility
    // dynamic behaviour :
    javaDocSwitchLabel.addMouseListener( new MouseAdapter()
     {
       public void mouseReleased( MouseEvent e )
       {
         // toggle
         if(javaDocSwitchLabel.getIcon() == OnIcon)
          {
            // Turn it off:
            int currentJavaDocPanelHeight = javaDocScrollPane.getSize().height;
            javaDocSwitchLabel.setIcon( OffIcon );
            javaDocScrollPane.setVisible(false);   // both containers must
            javaDocArea.setVisible(false);         // change visibility
            iniFile.setBooleanValue(JavaCheckBoxSelectionIniFileKey,false);

            // Set the divider location to maximum:
            splitPane.setDividerLocation(1.0d); // 1.0d == set max value
            splitPane.setDividerSize(0);

            // Make the window height smaller :
            Dimension actualSize = thisWindow.getSize();
            int newHeight = actualSize.height - currentJavaDocPanelHeight;
            if( newHeight < 4*fontSize ) newHeight = 4*fontSize;
            Dimension newSize = new Dimension( actualSize.width,newHeight );
            thisWindow.setSize( newSize );

          }
         else
          {
            javaDocSwitchLabel.setIcon( OnIcon );
            javaDocScrollPane.setVisible(true);   // both containers must
            javaDocArea.setVisible(true);        // change visibility
            iniFile.setBooleanValue(JavaCheckBoxSelectionIniFileKey,true);

            // Reset the divider :
            splitPane.setDividerSize(originalDividerSize);

            // Make the window height bigger :
            Dimension actualSize = thisWindow.getSize();
            int newHeight = actualSize.height + javaDocPanelHeight;
            Dimension newSize = new Dimension( actualSize.width,newHeight );
            thisWindow.setSize( newSize );
            // and update the JavaDoc content:
            if( javaDocArea.isVisible() )
             {
               Object selectedObject = list.getSelectedValue();
               if( selectedObject != null )
                {
                  if( selectedObject instanceof CodeCompletionListEntry )
                   {
                     CodeCompletionListEntry selectedEntry = (CodeCompletionListEntry)selectedObject;
                     javaDocArea.setText( selectedEntry.getJavaDoc() );
                     javaDocArea.setCaretPosition(0);
                   }
                }
             }
          }
         thisWindow.validate();
         thisWindow.repaint();
       }
     });

    // Track resizings. Adjust the splitpane position, when
    // JavaDoc is turned off: Keep it at max value :
    this.addComponentListener( new ComponentAdapter()
     {
       public void componentResized(ComponentEvent e)
       {
         if(javaDocSwitchLabel.getIcon() == OffIcon) // JavaDoc is turned off.
          {
            // Set the divider location to maximum:
            splitPane.setDividerLocation(1.0d); // 1.0d == set max value
          }
       }
     });

  } // buildTheJavaDocPanel





 


 /**
  *  Selects the listentry with the passed listIndex and
  *  tells the list view to scroll the selected line to visible.
  */
  public void selectAndScrollToListIndex( final JList list,
                                          final int listIndex )
  {
    if( ( listIndex >= 0 ) && ( listIndex < list.getModel().getSize() ) )
     {                              
       list.setSelectedIndex(listIndex);
       final Point selectedPoint = list.indexToLocation(listIndex);
       final int gap = UIManager.getFont("Label.font").getSize();
       if( selectedPoint != null )
        {              
          final Rectangle rect = new Rectangle( 0,selectedPoint.y,10,gap );
          list.scrollRectToVisible( rect );
        } 
       else
        {
          Log.Warn("selectedPoint was NULL");
        }
     }              
  } // selectAndScrollToListIndex





 /**
  *  Lets the editor jump to the file containing the method given by
  *  methodFSD and the fsd which contains that method fsd.
  *  If required, the search goes backward in the parentchain of the
  *  parentFSD, which is required, if the method isnt toplevel in parentFSD.
  */
  private void jumpToMethodInFile( final FileStructureDescriptionForMethod methodFSD,
                                   final FileStructureDescription parentFSD )
  {
    Runnable jumper = new Runnable()
     {
       public void run()
       {
         jumpToMethodInFile_OutsideEDT(methodFSD,parentFSD);
       }
     };
    ThreadEngine.getInstance().addRunnable(jumper,"JumpToMethod");
  }

                                                                

 /**
  *  Called by jumpToMethodInFile in a threadengine context.
  */
  private void jumpToMethodInFile_OutsideEDT( final FileStructureDescriptionForMethod methodFSD,
                                              final FileStructureDescription parentFSD )
  {
    int lineNumber = methodFSD.name.startLine - 1;
    // See if the methodFSD is toplevel, for which case we can make it
    // fast without having to create transient contents:
    if( this.isMethodFSDContainedInFSD(methodFSD,parentFSD) )
     {
       // Look in the ProjectFilesTree first :
       boolean fileWasFoundAndDisplayed = 
          this.projectFrame.getProjectFilesManager().getProjectFilesTree().showLeafByTreePathName( 
               parentFSD.fullyQualifiedClassNameBuffer,
               parentFSD.extension,
               lineNumber,
               0,
               true );
       // If it was not found there, look in the librariestree :
       if( !fileWasFoundAndDisplayed )                      
        {
          fileWasFoundAndDisplayed = this.projectFrame.getLibrariesTree().showLeafByTreePathName( 
                                        parentFSD.fullyQualifiedClassNameBuffer,
                                        parentFSD.extension,
                                        lineNumber,
                                        0,
                                        true );
        }
     }
    else
     {
       // Search the parentchain, until the methodFSD has been found :
       // Temporarily load the transient attributes (which also the parent chain belongs to)
       this.fileStructureDescriptionManager.updateTransientFieldsFor(parentFSD);
       FileStructureDescription basisFSD = null;
       for( int i=0; i < parentFSD.parentDescriptions.length; i++ )
        {
          if( this.isMethodFSDContainedInFSD(methodFSD,parentFSD.parentDescriptions[i]) )
           {
             basisFSD = parentFSD.parentDescriptions[i];
             break;
           }
        } // for
       // Prevent memory explosion: Free the transient fields again :
       this.fileStructureDescriptionManager.releaseTransientFieldsFor(parentFSD);
       if( basisFSD != null ) // found it in a parent fsd
        {
          // Look in the ProjectFilesTree first :
          boolean fileWasFoundAndDisplayed =
             this.projectFrame.getProjectFilesManager().getProjectFilesTree().showLeafByTreePathName(
                     basisFSD.fullyQualifiedClassNameBuffer,
                     basisFSD.extension,
                     lineNumber,
                     0,
                     false );
          // If it was not found there, look in the librariestree :
          if( !fileWasFoundAndDisplayed )
           {
             fileWasFoundAndDisplayed = this.projectFrame.getLibrariesTree().showLeafByTreePathName(
                                             basisFSD.fullyQualifiedClassNameBuffer,
                                             basisFSD.extension,
                                             lineNumber,
                                             0,
                                             true );
           }
        }
     } // else                                       

  } // jumpToMethodInFile




  

 /**
  *  Analog to jumpToMethodInFile, but for attributes.
  */
  private void jumpToFieldInFile( final FileStructureDescriptionForField fieldFSD,
                                  final FileStructureDescription parentFSD )
  {
    Runnable jumper = new Runnable()
     {
       public void run()
       {
         jumpToFieldInFile_OutsideEDT(fieldFSD,parentFSD);
       }
     };
    ThreadEngine.getInstance().addRunnable(jumper,"JumpToField");
  }





 /**
  *  Called by jumpToFieldInFile in a threadengine context.
  */
  private void jumpToFieldInFile_OutsideEDT( final FileStructureDescriptionForField fieldFSD,
                                             final FileStructureDescription parentFSD )
  {
    int lineNumber = fieldFSD.simpleClassName.startLine - 1;
    // See if the fieldFSD is toplevel, for which case we can make it
    // fast without having to create transient contents:
    if( this.isFieldFSDContainedInFSD(fieldFSD,parentFSD) )
     {
       // Look in the ProjectFilesTree first :
       boolean fileWasFoundAndDisplayed =
          this.projectFrame.getProjectFilesManager().getProjectFilesTree().showLeafByTreePathName(
                        parentFSD.fullyQualifiedClassNameBuffer,
                        parentFSD.extension,
                        lineNumber,
                        0,
                        false );
       // If it was not found there, look in the librariestree :
       if( !fileWasFoundAndDisplayed )
        {
          fileWasFoundAndDisplayed = this.projectFrame.getLibrariesTree().showLeafByTreePathName(
                                        parentFSD.fullyQualifiedClassNameBuffer,
                                        parentFSD.extension,
                                        lineNumber,
                                        0,
                                        true );
        }         
     }
    else
     {
       // Search the parentchain, until the methodFSD has been found :
       // Temporarily load the transient attributes (which also the parent chain belongs to)
       this.fileStructureDescriptionManager.updateTransientFieldsFor(parentFSD);
       FileStructureDescription basisFSD = null;
       for( int i=0; i < parentFSD.parentDescriptions.length; i++ )
        {
          if( this.isFieldFSDContainedInFSD(fieldFSD,parentFSD.parentDescriptions[i]) )
           {
             basisFSD = parentFSD.parentDescriptions[i];
             break;
           }
        } // for
       // Prevent memory explosion: Free the transient fields again :
       this.fileStructureDescriptionManager.releaseTransientFieldsFor(parentFSD);


       // If nothing has been found in the inherited parent chain, scan the chains of
       // the implemented interfaces. There are as many chains as implemented interfaces
       // for this class, because once we are in an interface, it only can extend another
       // interface (but not extend a class or implement anything )
       if( basisFSD == null )
        {
          FileStructureDescription workFSD = parentFSD;
          final Vector interfaceVector = workFSD.implementedInterfaces;
          // From each of the implemented interfaces there can start a chain
          // of further *extended* child interfaces (only interface extends interface allowed) :
          for( int q=0; q < interfaceVector.size(); q++ )
           {
             StringWithPosition interfaceEntry = (StringWithPosition)interfaceVector.elementAt(q);
             String interfaceQualifier = interfaceEntry.content;

             // Search this interface chain :
             FileStructureDescription[] interfaceParentFSDs = CodeCompletionUtilities.GetInterfaceChainForFSD( workFSD,interfaceQualifier,this.fileStructureDescriptionManager );
             for( int k=0; k < interfaceParentFSDs.length; k++ )
              {
                if( interfaceParentFSDs[k].containsTopLevelMemberAttributeWithName( fieldFSD.objectNameWithPosition.content ) )
                 {
                   basisFSD = interfaceParentFSDs[k];
                   break;
                 }
              }
           } // for
        } // if


       if( basisFSD != null ) // found it in a parent fsd
        {
          // Look in the ProjectFilesTree first :
          boolean fileWasFoundAndDisplayed =
            this.projectFrame.getProjectFilesManager().getProjectFilesTree().showLeafByTreePathName(
                   basisFSD.fullyQualifiedClassNameBuffer,
                   basisFSD.extension,
                   lineNumber,
                   0,
                   false );
          // If it was not found there, look in the librariestree :
          if( !fileWasFoundAndDisplayed )
           {
             fileWasFoundAndDisplayed =
                this.projectFrame.getLibrariesTree().showLeafByTreePathName(
                   basisFSD.fullyQualifiedClassNameBuffer,
                   basisFSD.extension,
                   lineNumber,
                   0,
                   true );
           }
        }
     } // else

  } // jumpToFieldInFile_OutsideEDT




 /**
  *  Analog to jumpToMethodInFile, but for static inner classes.
  */
  private void jumpToStaticInnerClassInFile( final FileStructureDescription staticInnerClassFSD,
                                             final FileStructureDescription parentFSD )
  {
    Runnable jumper = new Runnable()
     {
       public void run()
       {
         jumpToStaticInnerClassInFile_OutsideEDT( staticInnerClassFSD,parentFSD );
       }
     };
    ThreadEngine.getInstance().addRunnable(jumper,"JumpToStaticInnerClass");
  }

   
   
   
 /**
  *  Called by jumpToFieldInFile in a threadengine context.
  */                                             
  private void jumpToStaticInnerClassInFile_OutsideEDT( final FileStructureDescription staticInnerClassFSD,
                                                        final FileStructureDescription parentFSD )
  {
    int lineNumber = staticInnerClassFSD.scopeStartLine;
    // Look in the ProjectFilesTree first :
    boolean fileWasFoundAndDisplayed =
       this.projectFrame.getProjectFilesManager().getProjectFilesTree().showLeafByTreePathName(
                     parentFSD.fullyQualifiedClassNameBuffer,
                     parentFSD.extension,
                     lineNumber,
                     0,
                     false );
    // If it was not found there, look in the librariestree :
    if( !fileWasFoundAndDisplayed )
     {
       fileWasFoundAndDisplayed = this.projectFrame.getLibrariesTree().showLeafByTreePathName(
                                     parentFSD.fullyQualifiedClassNameBuffer,
                                     parentFSD.extension,
                                     lineNumber,
                                     0,
                                     true );
     }
  }



  private boolean isMethodFSDContainedInFSD( FileStructureDescriptionForMethod methodFSD,
                                             FileStructureDescription parentFSD )
  {
    boolean isContained = false;
    for( int i=0; i < parentFSD.methodDescriptions.size(); i++ )
     {
       FileStructureDescriptionForMethod mFsd = (FileStructureDescriptionForMethod)parentFSD.methodDescriptions.elementAt(i);
       if( mFsd == methodFSD ) // Reference comparison
        {
          isContained = true;
          break;
        }
     } // for
    return isContained;
  }




  private boolean isFieldFSDContainedInFSD( FileStructureDescriptionForField fieldFSD,
                                            FileStructureDescription parentFSD )
  {
    boolean isContained = false;
    for( int i=0; i < parentFSD.fieldDescriptions.size(); i++ )
     {
       FileStructureDescriptionForField fFsd = (FileStructureDescriptionForField)parentFSD.fieldDescriptions.elementAt(i);
       if( fFsd == fieldFSD ) // Reference comparison
        {
          isContained = true;
          break;
        }
     } // for
    return isContained;
  }




                       
  public class TitlePanel extends JPanel
  {
                           
    public TitlePanel( final String title )
    {
      super( new BorderLayout() );

      Color fgColor = UIManager.getColor("Menu.foreground");
      Color bgColor = UIManager.getColor("Menu.background");
      Color borderColor = null;
      // give a small contrast :
      int fgGray = ( fgColor.getRed() + fgColor.getGreen() + fgColor.getBlue() )/3;
      int bgGray = ( bgColor.getRed() + bgColor.getGreen() + bgColor.getBlue() )/3;
      if( fgGray > bgGray )
       {
         fgColor = this.slightlyBrighter(fgColor);
         bgColor = this.slightlyDarker(bgColor);
         borderColor = this.slightlyDarker(bgColor);
       } else
       {
         fgColor = this.slightlyDarker(fgColor);
         bgColor = this.slightlyBrighter(bgColor);
         borderColor = this.slightlyBrighter(bgColor);
       }
      this.setForeground( fgColor );
      this.setBackground( bgColor );
      final Border inb  = BorderFactory.createEmptyBorder(0,4,0,4);
      final Border outb = BorderFactory.createLineBorder(borderColor);
      this.setBorder( BorderFactory.createCompoundBorder(outb,inb) );
      final JContrastLabel titleLabel = new JContrastLabel(title);
      titleLabel.setForeground( fgColor );
      titleLabel.setBackground( bgColor );
      titleLabel.setFont(UIManager.getFont("Menu.font"));
      this.add( titleLabel, BorderLayout.CENTER );
    }


    private Color slightlyDarker( final Color c )
    {
      int r = c.getRed()   - 24; if( r < 0 ) r = 0;
      int g = c.getGreen() - 24; if( g < 0 ) g = 0;
      int b = c.getBlue()  - 24; if( b < 0 ) b = 0;
      return new Color(r,g,b);
    }

    private Color slightlyBrighter( final Color c )
    {
      int r = c.getRed()   + 24; if( r > 255 ) r = 255;
      int g = c.getGreen() + 24; if( g > 255 ) g = 255;
      int b = c.getBlue()  + 24; if( b > 255 ) b = 255;
      return new Color(r,g,b);
    }                                  

  } // inner class TitlePanel



} // CodeCompletion




     





















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.