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 }