View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.gui.component;
21  
22  import java.awt.event.InputEvent;
23  import java.awt.event.KeyAdapter;
24  import java.awt.event.KeyEvent;
25  import java.util.LinkedList;
26  
27  import javax.help.CSH;
28  import javax.swing.text.Document;
29  import javax.swing.*;
30  
31  /***
32   * Provides a text field with a history.
33   */
34  public class HistoryTextField extends JTextField
35  {
36  
37      //--- Constant(s) ---
38  
39      //--- Data field(s) ---
40  
41      /***
42       * A list of <code>String</code> objects.
43       */
44      private LinkedList history = new LinkedList();
45      /***
46       * A list of <code>String</code> objects.
47       */
48      private LinkedList future = new LinkedList();
49  
50  	/***
51  	 * 
52  	 */
53  	public HistoryTextField()
54  	{
55  		initialize();
56  	}
57  
58  	public HistoryTextField(String text) 
59  	{
60  		super(text);
61  		initialize();
62  	}
63  
64  	public HistoryTextField(int columns) 
65  	{
66  		super(columns);
67  		initialize();
68  	}
69  
70  	/***
71  	 * @param doc
72  	 * @param text
73  	 * @param columns
74  	 */
75  	public HistoryTextField(Document doc, String text, int columns)
76  	{
77  		super(doc, text, columns);
78  		initialize();
79  	}
80  
81      //--- Constructor(s) ---
82  
83      /***
84       * Constructs a new <code>HistoryTextField</code>.
85       */
86      public HistoryTextField(String text, int size)
87      {
88  		super(text, size);
89  		initialize();
90      }
91  
92  	//	--- Method(s) ---
93  
94  	private void initialize()
95  	{
96  		// register standard help text for component
97  		CSH.setHelpIDString(this, "historytextfield");
98  		
99  		addKeyListener(new KeyHandler());
100 	}
101 
102     //--- Inner Class(es) ---
103     
104     private class KeyHandler extends KeyAdapter
105     {
106 
107 		public void keyPressed(KeyEvent e)
108 		{
109 			if (e.isConsumed()) {
110 				return;
111 			}
112 
113 			int code = e.getKeyCode();
114 			int modifiers = e.getModifiers();
115 	    
116 			/* ENTER event: add item to history and completion */
117 			if (code == KeyEvent.VK_ENTER && getText().length() > 0) {
118 				/* if the user presses enter after an old history entry */
119 				if (future.size() > 0) {
120 					history.addAll(future);
121 					future.clear();
122 				}
123 				history.addLast(getText());
124 				//  getCompletionModel().insert(getText());
125 			}
126 			/* go back in history */
127 			else if ((code == KeyEvent.VK_P 
128 					  && modifiers == InputEvent.CTRL_MASK) 
129 					 || code == KeyEvent.VK_UP) {
130 				if (history.size() > 0) {
131 					if (getText().length() > 0) {
132 						future.addFirst(getText());
133 					}
134 					setText((String)history.removeLast());
135 				}
136 				else {
137 					getToolkit().beep();
138 				}
139 			}
140 			/* go forward in history */
141 			else if ((code == KeyEvent.VK_N
142 					  && modifiers == InputEvent.CTRL_MASK)
143 					 || code == KeyEvent.VK_DOWN) {
144 				if (future.size() > 0) {
145 					if (getText().length() > 0) {
146 						history.addLast(getText());
147 					}
148 					setText((String)future.removeFirst());
149 				}
150 				else if (getText().length() > 0) {
151 					history.addLast(getText());
152 					setText("");
153 				}
154 				else {
155 					getToolkit().beep();
156 				}
157 			}
158 			/* go to beginning of history */
159 			else if ((code == KeyEvent.VK_LESS 
160 					  && modifiers == InputEvent.ALT_MASK)
161 					 || (code == KeyEvent.VK_HOME 
162 						 && modifiers == InputEvent.CTRL_MASK)) {
163 				if (history.size() > 0) {
164 					if (getText().length() > 0) {
165 						history.addLast(getText());
166 					}
167 					future.addAll(0, history);
168 					history.clear();
169 					setText((String)future.removeFirst());
170 				}
171 				else {
172 					getToolkit().beep();
173 				}
174 			}
175 			/* go to the end of future */
176 			// FIX ME: this works only for German keyboard layouts
177 			else if ((code == KeyEvent.VK_LESS && modifiers 
178 					  == InputEvent.ALT_MASK + InputEvent.SHIFT_MASK)
179 					 || (code == KeyEvent.VK_END
180 						 && modifiers == InputEvent.CTRL_MASK)) {
181 				if (future.size() > 0) {
182 					if (getText().length() > 0) {
183 						future.addFirst(getText());
184 					}
185 					history.addAll(future);
186 					future.clear();
187 					setText("");
188 				}
189 				else if (getText().length() > 0) {
190 					history.addLast(getText());
191 					setText("");
192 				}
193 				else {
194 					getToolkit().beep();
195 				}
196 			}
197 		}
198     }
199 }