All Downloads are FREE. Search and download functionalities are using the official Maven repository.

editor.AbstractPopup Maven / Gradle / Ivy

There is a newer version: 1.18.1
Show newest version
/*
 *
 *  Copyright 2010 Guidewire Software, Inc.
 *
 */
package editor;

import editor.util.TextComponentUtil;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.text.JTextComponent;
import java.awt.*;


public abstract class AbstractPopup extends JPopupMenu implements IValuePopup
{
  private EventListenerList _nodeListenerList;
  private JTextComponent _editor;


  public AbstractPopup( JTextComponent editor )
  {
    super();
    _editor = editor;
    _nodeListenerList = new EventListenerList();
  }

  public abstract void setValue( Object value );

  public abstract void refresh();

  protected abstract void registerListeners();

  protected abstract void unregisterListeners();

  public JTextComponent getEditor()
  {
    return _editor;
  }

  @Override
  public void setVisible( boolean bVisible )
  {
    boolean wasVisible = isVisible();
    super.setVisible( bVisible );

    if( _editor == null )
    {
      return;
    }

    if( !wasVisible && bVisible )
    {
      registerListeners();
      editor.util.EditorUtilities.removePopupBorder( this );
    }
    else if( wasVisible && !bVisible )
    {
      unregisterListeners();
      _editor.requestFocus();
    }
  }

  @Override
  public void addNodeChangeListener( ChangeListener l )
  {
    _nodeListenerList.add( ChangeListener.class, l );
  }

  public void removeNodeChangeListener( ChangeListener l )
  {
    _nodeListenerList.remove( ChangeListener.class, l );
  }

  protected void fireNodeChanged( final ChangeEvent e )
  {
    // NOTE pdalbora 7-Apr-2008 -- This used to always fire the NodeChanged event in an
    // invokeLater(), but this was causing CC-39860: an event would fire when the user
    // clicked another cell in the table. All cells in a column share the same text editor.
    // So, the editor would be enabled on the new cell, and *then* the listener that sets
    // the value in the editor from that in the popup would run, because it had been queued
    // at the end of the event queue.
    if( SwingUtilities.isEventDispatchThread() )
    {
      fireNodeChangedNow( _nodeListenerList, e );
    }
    else
    {
      // TODO pdalbora 7-Apr-2008 -- Will this ever *not* be called on the UI thread? I.e.,
      // do we ever really need to do this in an invokeLater()?
      EventQueue.invokeLater( new Runnable()
      {
        @Override
        public void run()
        {
          fireNodeChangedNow( _nodeListenerList, e );
        }
      } );
    }
  }

  private void fireNodeChangedNow( EventListenerList list, ChangeEvent e )
  {
    // Guaranteed to return a non-null array
    Object[] listeners = list.getListenerList();

    // Process the listeners last to first,
    // notifying those that are interested in this event
    for( int i = listeners.length - 2; i >= 0; i -= 2 )
    {
      if( listeners[i] == ChangeListener.class )
      {
        ((ChangeListener)listeners[i + 1]).stateChanged( e );
      }
    }
  }

  protected String filterDisplay()
  {
    String strPrefix = TextComponentUtil.getWordAtCaret( _editor );
    if( strPrefix != null && strPrefix.length() > 0 &&
        (Character.isWhitespace( strPrefix.charAt( 0 ) ) || !Character.isJavaIdentifierPart( strPrefix.charAt( 0 ) )) )
    {
      strPrefix = TextComponentUtil.getPartialWordBeforeCaret( _editor );
      if( strPrefix != null && strPrefix.length() > 0 &&
          (Character.isWhitespace( strPrefix.charAt( 0 ) ) || !Character.isJavaIdentifierPart( strPrefix.charAt( 0 ) )) )
      {
        strPrefix = null;
      }
    }

    return strPrefix;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy