All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
editor.AbstractGotoPopup Maven / Gradle / Ivy
package editor;
import editor.util.ContainerMoverSizer;
import editor.util.ContainerSizer;
import editor.util.EditorUtilities;
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
/**
* Generic implementation of a popup. Refactored from original GotoTypePopup.
*/
public abstract class AbstractGotoPopup extends JPopupMenu
{
//----- Internal workings of popup -----//
protected GenerifiedJList _list;
protected JTextField _nameField;
private EventListenerList _nodeListenerList = new EventListenerList();
private boolean _bLocked;
private EditorKeyListener _editorKeyListener;
private UndoableEditListener _docListener;
private DocumentListener _docListenerForEdits;
private JScrollPane _scrollPane;
private JCheckBox _cbExternalTypes;
//----- Exposed pieces of the popup implementation -----//
/**
* Wait time between keystrokes
*/
private final int _waitTime;
private Timer _timer;
/**
* The visible row count for the popup
*/
private final int _rowCount;
private final String _title;
private List _allData;
private String _strPrefix;
private final boolean _takesInput;
private final boolean _centerInFrame;
private Object _dataLock = new Object();
private boolean _dataInitialized;
private JLabel _spinner;
private boolean _externalOption;
public AbstractGotoPopup( int waitTime, int rowCount, String title, String strPrefix, boolean takesInput, boolean centerInFrame, boolean externalOption )
{
_waitTime = waitTime;
_timer = new Timer();
_rowCount = rowCount;
_title = title;
_strPrefix = strPrefix;
_takesInput = takesInput;
_centerInFrame = centerInFrame;
_externalOption = externalOption;
initLayout();
}
private void initLayout()
{
setOpaque( false );
setDoubleBuffered( true );
GridBagLayout gridBag = new GridBagLayout();
JPanel pane = new JPanel();
pane.setLayout( gridBag );
GridBagConstraints c = new GridBagConstraints();
Border border = BorderFactory.createCompoundBorder(
UIManager.getBorder( "PopupMenu.border" ),
BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
ContainerMoverSizer content = new ContainerMoverSizer( border );
content.setLayout( new BorderLayout() );
_cbExternalTypes = new JCheckBox( "Include external types" );
initializeDataInWaitMode();
int iY = 0;
JLabel labelName = new JLabel( _title );
labelName.setOpaque( true );
labelName.setBackground( Scheme.active().getControl() );
labelName.setFont( labelName.getFont().deriveFont( Font.BOLD ) );
labelName.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = iY++;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 1;
c.weighty = 0;
pane.add( labelName, c );
if( _externalOption )
{
_cbExternalTypes.setBackground( Scheme.active().getControl() );
_cbExternalTypes.setMnemonic( 'n' );
_cbExternalTypes.addItemListener( e -> {
initializeDataInWaitMode();
handleEdit();
} );
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = iY-1;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 0;
c.weighty = 0;
pane.add( _cbExternalTypes, c );
}
if( _takesInput )
{
_nameField = new JTextField( 32 );
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = iY++;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 1;
c.weightx = 1;
c.weighty = 0;
c.insets = new Insets( 2, 0, 2, 0 );
pane.add( _nameField, c );
}
//
// The list
//
_scrollPane = new JScrollPane();
_list =
new GenerifiedJList( new DefaultListModel() )
{
@Override
public Dimension getPreferredScrollableViewportSize()
{
Dimension dim = super.getPreferredScrollableViewportSize();
int iScreenWidth = getToolkit().getScreenSize().width;
if( dim.width > iScreenWidth / 3 )
{
dim.width = iScreenWidth / 3;
}
return dim;
}
};
_scrollPane.setViewportView( _list );
_scrollPane.setVisible( false );
_list.addMouseListener( new PopupMouseListener() );
_list.setCellRenderer( constructCellRenderer() );
_list.setFixedCellHeight( 22 );
_list.getSelectionModel().setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
_list.setVisibleRowCount( _rowCount );
_scrollPane.setBorder( UIManager.getBorder( "TextField.border" ) );
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = iY++;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 1;
c.weightx = 1;
c.weighty = 1;
pane.add( _scrollPane, c );
_spinner = new JLabel( EditorUtilities.loadIcon( "images/wait.gif" ) );
_spinner.setBorder( UIManager.getBorder( "TextField.border" ) );
_spinner.setBackground( Scheme.active().getWindow() );
_spinner.setOpaque( true );
_spinner.setVisible( false );
c.gridy = iY;
pane.add( _spinner, c );
content.add( pane, BorderLayout.CENTER );
JPanel sizerPanel = new JPanel( new BorderLayout() );
sizerPanel.add( new JPanel(), BorderLayout.CENTER );
sizerPanel.add( new ContainerSizer(), BorderLayout.EAST );
content.add( sizerPanel, BorderLayout.SOUTH );
_editorKeyListener = new EditorKeyListener();
add( content );
_docListener = new UndoableEditListener()
{
@Override
public void undoableEditHappened( UndoableEditEvent e )
{
resetTimer();
}
};
_docListenerForEdits = new DocumentListener()
{
@Override
public void insertUpdate( DocumentEvent e )
{
resetTimer();
}
@Override
public void removeUpdate( DocumentEvent e )
{
resetTimer();
}
@Override
public void changedUpdate( DocumentEvent e )
{
resetTimer();
}
};
if( _strPrefix != null )
{
filterDisplay( _strPrefix, false );
}
EventQueue.invokeLater(
new Runnable()
{
@Override
public void run()
{
if( _takesInput )
{
_nameField.requestFocus();
}
else
{
_list.requestFocus();
}
}
} );
}
JTextField getNameField()
{
return _nameField;
}
GenerifiedJList getList()
{
return _list;
}
protected abstract ListCellRenderer constructCellRenderer();
protected abstract void handleEdit();
protected boolean isExternalTypes()
{
return _cbExternalTypes.isSelected();
}
private void initializeDataInWaitMode()
{
editor.util.EditorUtilities.doBackgroundOp(
() -> {
try
{
_allData = initializeData();
}
finally
{
_dataInitialized = true;
synchronized( _dataLock )
{
_dataLock.notifyAll();
}
SwingUtilities.invokeLater( () -> _spinner.setVisible( false ) );
}
} );
}
protected abstract List initializeData();
protected abstract AbstractPopupListModel reconstructModel( String prefix );
@Override
public final void setVisible( boolean bVisible )
{
super.setVisible( bVisible );
if( bVisible )
{
registerListeners();
editor.util.EditorUtilities.removePopupBorder( this );
turnOnMnemonics();
}
else
{
unregisterListeners();
if( _takesInput )
{
_nameField.requestFocus();
}
turnOffMnemonics();
}
}
private void turnOnMnemonics()
{
UIManager.getDefaults().put( "Button.showMnemonics", true );
EventQueue.invokeLater( () -> UIManager.getDefaults().put( "Button.showMnemonics", false ) );
}
private void turnOffMnemonics()
{
try
{
Robot robot = new Robot();
robot.keyPress( KeyEvent.VK_ALT );
robot.keyRelease( KeyEvent.VK_ALT );
}
catch( AWTException e )
{
// eat
}
}
private void registerListeners()
{
unregisterListeners();
if( _takesInput )
{
_nameField.addKeyListener( _editorKeyListener );
_nameField.getDocument().addUndoableEditListener( _docListener );
_nameField.getDocument().addDocumentListener( _docListenerForEdits );
}
else
{
_list.addKeyListener( _editorKeyListener );
}
}
private void unregisterListeners()
{
if( _takesInput )
{
_nameField.getDocument().removeDocumentListener( _docListenerForEdits );
_timer.cancel();
_nameField.getDocument().removeUndoableEditListener( _docListener );
_nameField.removeKeyListener( _editorKeyListener );
}
else
{
_list.removeKeyListener( _editorKeyListener );
}
}
protected void filterDisplay( final String prefix, boolean showSpinner )
{
if( showSpinner )
{
synchronized( _dataLock )
{
if( !_dataInitialized )
{
SwingUtilities.invokeLater( new Runnable()
{
@Override
public void run()
{
_spinner.setVisible( true );
pack();
_nameField.requestFocus();
}
} );
}
}
}
if( _takesInput )
{
editor.util.EditorUtilities.doBackgroundOp( new Runnable()
{
@Override
public void run()
{
final AbstractListModel model = reconstructModel( prefix );
SwingUtilities.invokeLater( new Runnable()
{
@Override
public void run()
{
filterSynchronously( model );
}
} );
}
} );
}
else
{
final AbstractListModel model = reconstructModel( prefix );
filterSynchronously( model );
}
}
private void filterSynchronously( AbstractListModel model )
{
_list.setModel( model );
_list.setSelectedIndex( 0 );
int iListCount = _list.getModel().getSize();
_list.setVisibleRowCount( Math.min( iListCount, _rowCount ) );
_scrollPane.setVisible( iListCount > 0 );
_list.revalidate();
_list.repaint();
pack();
if( _takesInput )
{
_nameField.requestFocus();
SwingUtilities.invokeLater( new Runnable()
{
@Override
public void run()
{
_nameField.requestFocus();
}
} );
}
}
@Override
public final void show( Component invoker, int iX, int iY )
{
_bLocked = true;
try
{
super.show( invoker, iX, iY );
if( _centerInFrame )
{
editor.util.EditorUtilities.centerWindowInFrame( this, KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() );
}
}
finally
{
_bLocked = false;
}
}
public final void addNodeChangeListener( ChangeListener l )
{
_nodeListenerList.add( ChangeListener.class, l );
}
public final void removeNodeChangeListener( ChangeListener l )
{
_nodeListenerList.remove( ChangeListener.class, l );
}
public void setSelection( String strSelection )
{
//iterate over _list and search for a match by name
List suggestionNames = getPopupSuggestions();
for( int currentIndex = 0; currentIndex < suggestionNames.size(); currentIndex++ )
{
if( suggestionNames.get( currentIndex ).equals( strSelection ) )
{
//select the matching suggestion's index
_list.setSelectedIndex( currentIndex );
break;
}
}
}
public List getPopupSuggestions()
{
ListModel popupModel = _list.getModel();
ArrayList suggestionNames = new ArrayList();
for( int i = 0; i < popupModel.getSize(); i++ )
{
suggestionNames.add( popupModel.getElementAt( i ).toString() );
}
return suggestionNames;
}
private void fireNodeChanged( final EventListenerList list, final ChangeEvent e )
{
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
fireNodeChangedNow( list, 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 );
}
}
}
/**
*/
class EditorKeyListener extends KeyAdapter
{
@Override
public void keyPressed( KeyEvent e )
{
if( e.isAltDown() )
{
if( e.getKeyChar() == 'n' )
{
_cbExternalTypes.setSelected( !_cbExternalTypes.isSelected() );
}
}
else if( e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_KP_UP )
{
Action selectPrevious = _list.getActionMap().get( "selectPreviousRow" );
selectPrevious.actionPerformed( new ActionEvent( _list, 0, "selectPreviousRow" ) );
}
else if( e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_KP_DOWN )
{
Action selectNext = _list.getActionMap().get( "selectNextRow" );
selectNext.actionPerformed( new ActionEvent( _list, 0, "selectNextRow" ) );
}
else if( e.getKeyCode() == KeyEvent.VK_PAGE_UP )
{
Action scrollUpChangeSelection = _list.getActionMap().get( "scrollUp" );
scrollUpChangeSelection.actionPerformed( new ActionEvent( _list, 0, "scrollUp" ) );
}
else if( e.getKeyCode() == KeyEvent.VK_PAGE_DOWN )
{
Action scrollDownChangeSelection = _list.getActionMap().get( "scrollDown" );
scrollDownChangeSelection.actionPerformed( new ActionEvent( _list, 0, "scrollDown" ) );
}
else if( e.getKeyCode() == KeyEvent.VK_ENTER )
{
T datum = _list.getSelectedValue();
if( datum != null )
{
fireNodeChanged( _nodeListenerList, new ChangeEvent( datum ) );
}
setVisible( false );
}
else if( e.getKeyCode() == KeyEvent.VK_ESCAPE )
{
setVisible( false );
}
else
{
return;
}
e.consume();
}
}
protected List getInitializedAllData()
{
synchronized( _dataLock )
{
if( !_dataInitialized )
{
try
{
_dataLock.wait();
}
catch( InterruptedException e )
{
throw new RuntimeException( e );
}
}
}
return _allData;
}
/**
*/
private class PopupMouseListener extends MouseAdapter
{
@Override
public void mouseClicked( MouseEvent e )
{
if( _bLocked )
{
return;
}
int iIndex = _list.locationToIndex( e.getPoint() );
if( iIndex < 0 )
{
return;
}
_list.setSelectedIndex( iIndex );
T datum = _list.getSelectedValue();
// BeanInfoNode node = tree.getBeanNode();
// if( !(node.getType() instanceof BeanType) )
// {
//
fireNodeChanged( _nodeListenerList, new ChangeEvent( datum ) );
setVisible( false );
// }
}
}
public static abstract class AbstractPopupListModel extends AbstractListModel
{
@Override
public abstract T getElementAt( int index );
}
protected abstract class GenerifiedJList extends JList
{
protected GenerifiedJList( ListModel dataModel )
{
super( dataModel );
}
protected GenerifiedJList( final T[] listData )
{
super( listData );
}
@Override
public T getSelectedValue()
{
return (T)super.getSelectedValue();
}
}
private void resetTimer()
{
DisplayListTimerTask timerTask = new DisplayListTimerTask();
if( _waitTime > 0 )
{
_timer.cancel();
_timer = new Timer();
_timer.schedule( timerTask, _waitTime );
}
else
{
timerTask.run();
}
}
private class DisplayListTimerTask extends TimerTask
{
@Override
public void run()
{
handleEdit();
}
}
}