001    /*
002     * This file is part of muCommander, http://www.mucommander.com
003     * Copyright (C) 2002-2008 Maxence Bernard
004     *
005     * muCommander is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation; either version 3 of the License, or
008     * (at your option) any later version.
009     *
010     * muCommander is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    
019    package com.mucommander.ui.autocomplete;
020    
021    import com.mucommander.ui.combobox.EditableComboBox;
022    
023    import javax.swing.text.BadLocationException;
024    import javax.swing.text.Document;
025    import javax.swing.text.JTextComponent;
026    import java.awt.*;
027    import java.awt.event.FocusListener;
028    import java.awt.event.KeyAdapter;
029    import java.awt.event.KeyEvent;
030    import java.awt.event.KeyListener;
031    import java.util.Vector;
032    
033    /**
034     * AutocompleterTextComponent convert any text component to auto-completion supported text component. 
035     * In order to support auto-completion two abstract methods need to be implemented:
036     * <ul>
037     *   <li>OnEnterPressed - What should the text component do when enter key is pressed and there is no item selected on the auto-completion popup list</li>
038     *   <li>OnEscPressed - What should the text component do when escape key is pressed and there is no item selected on the auto-completion popup list</li>
039     * </ul>
040     * 
041     * @author Arik Hadas
042     */
043    
044    public abstract class AutocompleterTextComponent {
045            private JTextComponent textComponent;
046            private EditableComboBox editableComboBox = null;
047            
048            public AutocompleterTextComponent(JTextComponent textComp) {
049                    this.textComponent = textComp;  
050            }
051            
052            protected AutocompleterTextComponent(EditableComboBox editableComboBox) {
053                    this.textComponent = editableComboBox.getTextField();
054                    this.editableComboBox = editableComboBox;
055                    
056                    // Remove all key listeners which are defined for the EditableCombobox
057                    removeAllKeyListeners();
058            }       
059    
060            // Abstract methods:
061            /**
062             * This function will be called when the text component has the focus and enter key is 
063             * pressed, while the auto-completion popup window is unvisible.
064             */
065            public abstract void OnEnterPressed(KeyEvent keyEvent);
066            
067            /**
068             * This function will be called when the text component has the focus and escape key is 
069             * pressed, while the auto-completion popup window is unvisible.
070             */
071            public abstract void OnEscPressed(KeyEvent keyEvent);
072            
073            private void removeAllKeyListeners() {
074                    KeyListener[] l = editableComboBox.getTextField().getKeyListeners();
075                    int nbKeyListeners = l.length;
076                    for (int i=0 ; i<nbKeyListeners; i++)
077                            editableComboBox.getTextField().removeKeyListener(l[i]);
078            }
079            
080            // Methods of the text component which are used by the auto-completion mechanism:       
081            public Document getDocument() { return textComponent.getDocument(); }
082            
083            public boolean isShowing() { return textComponent.isShowing(); }
084            
085            public void setText(String text) { textComponent.setText(text); }
086            
087            public String getText() { return textComponent.getText(); }
088                    
089            public boolean hasFocus() { return textComponent.hasFocus(); }
090            
091            public boolean isEnabled() { return textComponent.isEnabled(); }
092            
093            public int getCaretPosition() { return textComponent.getCaretPosition(); }
094            
095            public void requestFocus() { textComponent.requestFocus(); }
096            
097            public int getHeight() { return textComponent.getHeight(); }
098            
099            public Rectangle modelToView() throws BadLocationException { return textComponent.getUI().modelToView(textComponent, textComponent.getCaretPosition()); }
100    
101            public void moveCarentToEndOfText() { textComponent.setCaretPosition(textComponent.getText().length()); }
102            
103            public boolean isCarentAtEndOfTextAtInsertion() { return textComponent.getCaretPosition() == textComponent.getText().length() - 1; }
104            
105            public boolean isCarentAtEndOfTextAtRemoval() { return textComponent.getCaretPosition() == textComponent.getText().length() + 1; }
106            
107            public JTextComponent getTextComponent() { return textComponent; }
108            
109            public void addKeyListener(KeyAdapter adapter) { textComponent.addKeyListener(adapter); }
110            
111            public void addFocusListener(FocusListener listener) { textComponent.addFocusListener(listener); }
112            
113            
114            /**
115             *      getItemsNames
116             * 
117             * @return empty Vector if component is not an EditableComboBox,
118             *  otherwise return Vector which contains the names of the combobox items.
119             */
120            public Vector getItemNames() {
121                    Vector result = new Vector();
122                    if (editableComboBox != null) {
123                            int nbItems = editableComboBox.getItemCount();
124                            for (int i=0; i < nbItems; i++)
125                                    result.add(editableComboBox.getItemAt(i).toString());
126                    }
127                    return result;
128            }
129            
130            /**
131             * isPopupVisible
132             * 
133             * @return false if component is not an EditableComboBox,
134             *      otherwise, true if the combo-box list of items is visible.
135             */
136            public boolean isComponentsPopupVisible() {
137                    return editableComboBox == null ? false : editableComboBox.isPopupVisible();
138            }
139            
140            /**
141             * setPopupUnvisibe - make the combo-box list of items unvisible.
142             */
143            public void setComponentsPopupUnvisibe() {
144                    if (editableComboBox != null)
145                            editableComboBox.setPopupVisible(false);
146            }
147    }