alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.ext.java;

import java.awt.Cursor;
import java.awt.Dialog;
import java.awt.event.*;
import java.util.List;
import javax.swing.*;

import org.netbeans.editor.DialogSupport;
import org.netbeans.editor.LocaleSupport;
import org.netbeans.editor.WeakTimerListener;
import org.netbeans.editor.ext.ListCompletionView;

/**
 *
 * @author Miloslav Metelka
 * @version 1.0
 */

abstract public class JavaFastOpen implements ActionListener {
    
    private static final int TIMER_DELAY = 1000;
    
    private JavaFastOpenPanel panel;
    
    private ListCellRenderer cellRenderer;
    
    private JList resultList;
    
    private Dialog dialog;
    
    private JButton[] buttons;

    private Evaluator evaluator;

    private static Timer timer;
    
    
    
    private static final int SET_EXP = 1;
    private static final int POPULATE_LIST = 2;
    private static final int OPEN = 3;
    
    /** Reference to instance of this class. Used for showing only one
     * FastOpen dialog */
    protected static JavaFastOpen fastOpen = null;

    public JavaFastOpen() {
        timer = new Timer(0, new WeakTimerListener(this)); // delay will be set later
        timer.setRepeats(false);
    }
    
    public void setDialogVisible(boolean visible) {
        if (dialog == null) {
            dialog = createDialog();
        }
        
        dialog.setVisible(visible);

        if (visible) {
            getPanel().popupNotify();

        } else {

            if (evaluator != null) {
                evaluator.breakLoop();
            }

            dialog.dispose();
            fastOpen = null;
        }
    }
    
    /**
     * @param order for the equal items the order can be used to uniquely 
     *    distinguish them. This is sort of temporary trick which should be 
     *    replaced by better solution.
     */
    protected void openSource(Object item, int order) {
    }

    protected ListCellRenderer createCellRenderer() {
        JCCellRenderer rr = new JCCellRenderer();
        //rr.setClassDisplayFullName(true);
        return rr;
    }
    
    protected JList createResultList() {
        JList list = new ListCompletionView(getCellRenderer());
        list.addMouseListener(new MouseAdapter() {
             public void mouseClicked(MouseEvent e) {
                 if (e.getClickCount() == 2) {
                     actionPerformed(new ActionEvent(getButtons()[0], 0, ""));
                 }
             }
        });

        return list;
    }
    
    protected JButton[] getButtons() {
        if (buttons == null) {
            buttons = new JButton[] {
                new JButton(LocaleSupport.getString("JFO_openSourceButton", "Open Source")), // NOI18N
                new JButton(LocaleSupport.getString("JFO_closeButton", "Close")) // NOI18N
            };
            buttons[0].setEnabled (false);

            String mnemonic = LocaleSupport.getString("JFO_openSourceButtonMnemonic", "O"); // NOI18N
            if (mnemonic != null && mnemonic.length() > 0) {
                buttons[0].setMnemonic(mnemonic.charAt(0));
            }
            
            mnemonic = LocaleSupport.getString("JFO_closeButtonMnemonic", "C"); // NOI18N
            if (mnemonic != null && mnemonic.length() > 0) {
                buttons[1].setMnemonic(mnemonic.charAt(0));
            }
            buttons[0].getAccessibleContext().setAccessibleDescription(LocaleSupport.getString("ACSD_JFO_openSourceButton")); // NOI18N
            buttons[1].getAccessibleContext().setAccessibleDescription(LocaleSupport.getString("ACSD_JFO_closeButton")); // NOI18N
        }
        
        return buttons;
    }
    
    private Dialog createDialog() {
        String title = LocaleSupport.getString("JFO_title", "Open Java Source");

        Dialog dialog = DialogSupport.createDialog(title,
            getPanel(), false, getButtons(), false, 0, 1, this);
        dialog.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                JavaFastOpen.this.setDialogVisible(false);
            }
            
            public void windowClosed(WindowEvent evt) {
                // #33968 - focus returned to original document after Alt-Shift-O
                // Utilities.returnFocus();
            }
            
        });        

        return dialog;
    }

    protected JavaFastOpenPanel getPanel() {
        if (panel == null) {
            panel = new JavaFastOpenPanel(this);
        }
        return panel;
    }
    
    ListCellRenderer getCellRenderer() {
        if (cellRenderer == null) {
            cellRenderer = createCellRenderer();
        }
        return cellRenderer;
    }
    
    protected JList getResultList() {
        if (resultList == null) {
            resultList = createResultList();
        }
        return resultList;
    }
    
    private Evaluator getEvaluator() {
        if (evaluator == null) {
            evaluator = new Evaluator(0);
            org.openide.util.RequestProcessor.getDefault().post(evaluator);
        }
        return evaluator;
    }

    public void setSearchText (String text) {
        getPanel().setSearchText (text);
        postUpdate();
    }
    
    void postUpdate() {
        SwingUtilities.invokeLater(new Evaluator(SET_EXP));
    }
    
    protected abstract List findClasses(String exp);

    List evaluate(String exp) {
        List ret = null;

        if (exp != null && exp.length() > 0) {
            timer.setInitialDelay(TIMER_DELAY);
            timer.setDelay(TIMER_DELAY);
            timer.start();
            ret = findClasses(exp);
            timer.stop();
            getPanel().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
        
        return ret;
    }

    void populate(List result) {
        if (result != null) {
            if (getResultList() instanceof ListCompletionView) {
                SwingUtilities.invokeLater (new Evaluator(POPULATE_LIST, result));
            }
        }
    }
    
    private String listActionFor(KeyEvent ev) {
        InputMap map = resultList.getInputMap();
        Object o = map.get(KeyStroke.getKeyStrokeForEvent(ev));
        if (o instanceof String) {
            return (String)o;
        } else {
            return null;
        }
    }

    boolean boundScrollingKey(KeyEvent ev) {
        String action = listActionFor(ev);
        // See BasicListUI, MetalLookAndFeel:
        return "selectPreviousRow".equals(action) || // NOI18N
        "selectNextRow".equals(action) || // NOI18N
        "selectFirstRow".equals(action) || // NOI18N
        "selectLastRow".equals(action) || // NOI18N
        "scrollUp".equals(action) || // NOI18N
        "scrollDown".equals(action); // NOI18N
    }
    
    void delegateScrollingKey(KeyEvent ev) {
        String action = listActionFor(ev);
        Action a = resultList.getActionMap().get(action);
        if (a != null) {
            a.actionPerformed(new ActionEvent(resultList, 0, action));
        }
    }
    

    

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent evt) {
        Object src = evt.getSource();

        if (src == buttons[0] || src == panel ) { // Open button
            getEvaluator().postOpen();
        } else if (src instanceof Timer){
            getPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        } else {
            setDialogVisible(false);
        } 
    }

    private void open() {
        SwingUtilities.invokeLater(new Evaluator(OPEN));
    }

    private class Evaluator implements Runnable {
        
        private int opID;
        
        private List result;
        
        private String exp;
        
        private String lastExp;
        
        private boolean open;
        
        private boolean exit;
        
        Evaluator(int opID) {
            this(opID, null);
        }
        
        Evaluator(int opID, List result) {
            this.opID = opID;
            this.result = result;
        }
        
        synchronized void setExp(String exp) {
            this.exp = exp;
        }
        
        synchronized void postOpen() {
            this.open = true;
        }
        
        void breakLoop() {
            exit = true;
        }
        
        public void run() {
            switch (opID) {
                case SET_EXP:
                    String text = getPanel().getSearchText();
                    
                    // We enable immediately after first typed character
                    if (getEvaluator().lastExp == null && text.length() > 0) {
                        getButtons()[0].setEnabled(true);
                    }

                    getEvaluator().setExp(text);
                    return;
                    
                case POPULATE_LIST:
                    ((ListCompletionView)getResultList()).setResult(result);
                    getResultList().setSelectedIndex (0);
                    getButtons()[0].setEnabled( result.size() > 0);

                    if (dialog instanceof JDialog) {
                        JDialog jd = (JDialog)dialog;
                        jd.getRootPane ().setDefaultButton(
                            getButtons()[0].isEnabled() ? getButtons()[0] : null);
                    }
                    return;
                    
                case OPEN:
                    int selIndex = getResultList().getSelectedIndex();
                    if (selIndex >= 0) {
                        
                        // This is sort of temporary trick and better solution
                        // should be provided. But it should work reliably.
                        // If there are multiple classes with the same name
                        // at least pass to openSource method its index so that
                        // it can distinguish them:
                        int index = selIndex;
                        while (index > 0 && getResultList().getModel().getElementAt(selIndex).equals(
                                getResultList().getModel().getElementAt(index-1))) {
                            index--;
                        }
                        
                        openSource(getResultList().getModel().getElementAt(selIndex), selIndex - index);
                        setDialogVisible(false);
                    }
                    return;
            }

            // regular evaluator behavior
            try {
                while (!exit) {
                    if (exp != null && !exp.equals(lastExp)) {
                        lastExp = exp;
                        if (lastExp != null) {
                            List result = evaluate(lastExp);

                            if (lastExp.equals(exp)) {
                                populate(result);
                            }
                        }

                    }

                    synchronized (Evaluator.this) {
                        if (exp != null && exp.equals(lastExp) && open) {
                            JavaFastOpen.this.open();
                            this.open = false;
                        }
                    }

                    Thread.sleep(200);
                }

            } catch (InterruptedException e) {
            }
        }
        
    }
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.