001: /*
002: * HistoryTextField.java - Text field with a history
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1999, 2000, 2001 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.gui;
024:
025: //{{{ Imports
026: import javax.swing.*;
027: import javax.swing.border.Border;
028: import javax.swing.border.AbstractBorder;
029: import javax.swing.border.CompoundBorder;
030: import javax.swing.event.MouseInputAdapter;
031: import java.awt.*;
032: import java.awt.event.*;
033: import org.gjt.sp.jedit.*;
034:
035: //}}}
036:
037: /**
038: * Text field with an arrow-key accessable history.
039: * @author Slava Pestov
040: * @version $Id: HistoryTextField.java 10575 2007-09-14 02:31:49Z ezust $
041: */
042: public class HistoryTextField extends JTextField {
043: //{{{ HistoryTextField constructor
044: /**
045: * Creates a new history text field.
046: * @since jEdit 3.2pre5
047: */
048: public HistoryTextField() {
049: this (null);
050: } //}}}
051:
052: //{{{ HistoryTextField constructor
053: /**
054: * Creates a new history text field.
055: * @param name The history model name
056: */
057: public HistoryTextField(String name) {
058: this (name, false, true);
059: } //}}}
060:
061: //{{{ HistoryTextField constructor
062: /**
063: * Creates a new history text field.
064: * @param name The history model name
065: * @param instantPopups If true, selecting a value from the history
066: * popup will immediately fire an ActionEvent. If false, the user
067: * will have to press 'Enter' first
068: *
069: * @since jEdit 2.2pre5
070: */
071: public HistoryTextField(String name, boolean instantPopups) {
072: this (name, instantPopups, true);
073: } //}}}
074:
075: //{{{ HistoryTextField constructor
076: /**
077: * Creates a new history text field.
078: * @param name The history model name
079: * @param instantPopups If true, selecting a value from the history
080: * popup will immediately fire an ActionEvent. If false, the user
081: * will have to press 'Enter' first
082: * @param enterAddsToHistory If true, pressing the Enter key will
083: * automatically add the currently entered text to the history.
084: *
085: * @since jEdit 2.6pre5
086: */
087: public HistoryTextField(String name, boolean instantPopups,
088: boolean enterAddsToHistory) {
089: controller = new HistoryText(this , null) {
090: public void fireActionPerformed() {
091: HistoryTextField.this .fireActionPerformed();
092: }
093: };
094:
095: setModel(name);
096: MouseHandler mouseHandler = new MouseHandler();
097: addMouseListener(mouseHandler);
098: addMouseMotionListener(mouseHandler);
099:
100: setInstantPopups(instantPopups);
101: setEnterAddsToHistory(enterAddsToHistory);
102: } //}}}
103:
104: //{{{ setInstantPopups() method
105: /**
106: * Sets if selecting a value from the popup should immediately fire
107: * an ActionEvent.
108: * @since jEdit 4.0pre3
109: */
110: public void setInstantPopups(boolean instantPopups) {
111: controller.setInstantPopups(instantPopups);
112: } //}}}
113:
114: //{{{ getInstantPopups() method
115: /**
116: * Returns if selecting a value from the popup should immediately fire
117: * an ActionEvent.
118: * @since jEdit 4.0pre3
119: */
120: public boolean getInstantPopups() {
121: return controller.getInstantPopups();
122: } //}}}
123:
124: //{{{ setEnterAddsToHistory() method
125: /**
126: * Sets if pressing Enter should automatically add the currently
127: * entered text to the history.
128: * @since jEdit 4.0pre3
129: */
130: public void setEnterAddsToHistory(boolean enterAddsToHistory) {
131: this .enterAddsToHistory = enterAddsToHistory;
132: } //}}}
133:
134: //{{{ getEnterAddsToHistory() method
135: /**
136: * Returns if pressing Enter should automatically add the currently
137: * entered text to the history.
138: * @since jEdit 4.0pre3
139: */
140: public boolean setEnterAddsToHistory() {
141: return enterAddsToHistory;
142: } //}}}
143:
144: //{{{ setSelectAllOnFocus() method
145: /**
146: * Sets if all text should be selected when the field gets focus.
147: * @since jEdit 4.0pre3
148: */
149: public void setSelectAllOnFocus(boolean selectAllOnFocus) {
150: this .selectAllOnFocus = selectAllOnFocus;
151: } //}}}
152:
153: //{{{ getSelectAllOnFocus() method
154: /**
155: * Returns if all text should be selected when the field gets focus.
156: * @since jEdit 4.0pre3
157: */
158: public boolean setSelectAllOnFocus() {
159: return selectAllOnFocus;
160: } //}}}
161:
162: //{{{ getModel() method
163: /**
164: * Returns the underlying history model.
165: */
166: public HistoryModel getModel() {
167: return controller.getModel();
168: } //}}}
169:
170: //{{{ setModel() method
171: /**
172: * Sets the history list model.
173: * @param name The model name
174: * @since jEdit 2.3pre3
175: */
176: public void setModel(String name) {
177: controller.setModel(name);
178:
179: if (name != null) {
180: setBorder(new CompoundBorder(this .getBorder(),
181: new HistoryBorder()));
182: }
183:
184: repaint();
185: } //}}}
186:
187: //{{{ addCurrentToHistory() method
188: /**
189: * Adds the currently entered item to the history.
190: */
191: public void addCurrentToHistory() {
192: controller.addCurrentToHistory();
193: } //}}}
194:
195: //{{{ setText() method
196: /**
197: * Sets the displayed text.
198: */
199: public void setText(String text) {
200: super .setText(text);
201: controller.setIndex(-1);
202: } //}}}
203:
204: //{{{ fireActionPerformed() method
205: /**
206: * Make it public.
207: */
208: public void fireActionPerformed() {
209: super .fireActionPerformed();
210: } //}}}
211:
212: //{{{ Protected members
213:
214: //{{{ processKeyEvent() method
215: protected void processKeyEvent(KeyEvent evt) {
216: if (!isEnabled())
217: return;
218:
219: if (evt.getID() == KeyEvent.KEY_PRESSED) {
220: switch (evt.getKeyCode()) {
221: case KeyEvent.VK_ENTER:
222: if (enterAddsToHistory)
223: addCurrentToHistory();
224:
225: if (evt.getModifiers() == 0) {
226: fireActionPerformed();
227: evt.consume();
228: }
229: break;
230: case KeyEvent.VK_UP:
231: if (evt.isShiftDown())
232: controller.doBackwardSearch();
233: else
234: controller.historyPrevious();
235: evt.consume();
236: break;
237: case KeyEvent.VK_DOWN:
238: if (evt.isShiftDown())
239: controller.doForwardSearch();
240: else if (evt.isAltDown()) {
241: controller.showPopupMenu(evt.isShiftDown());
242: } else
243: controller.historyNext();
244: evt.consume();
245: break;
246: case KeyEvent.VK_TAB:
247: if (evt.isControlDown()) {
248: controller.doBackwardSearch();
249: evt.consume();
250: }
251: break;
252: }
253: }
254:
255: if (!evt.isConsumed())
256: super .processKeyEvent(evt);
257: } //}}}
258:
259: //{{{ processMouseEvent() method
260: protected void processMouseEvent(MouseEvent evt) {
261: if (!isEnabled())
262: return;
263:
264: switch (evt.getID()) {
265: case MouseEvent.MOUSE_PRESSED:
266: Border border = getBorder();
267: Insets insets = border
268: .getBorderInsets(HistoryTextField.this );
269:
270: if (evt.getX() >= getWidth() - insets.right
271: || GUIUtilities.isPopupTrigger(evt)) {
272: controller.showPopupMenu(evt.isShiftDown());
273: } else
274: super .processMouseEvent(evt);
275:
276: break;
277: case MouseEvent.MOUSE_EXITED:
278: setCursor(Cursor.getDefaultCursor());
279: super .processMouseEvent(evt);
280: break;
281: default:
282: super .processMouseEvent(evt);
283: break;
284: }
285: } //}}}
286:
287: //}}}
288:
289: //{{{ Private members
290:
291: //{{{ Instance variables
292: private HistoryText controller;
293: private boolean enterAddsToHistory;
294: private boolean selectAllOnFocus;
295:
296: //}}}
297:
298: //}}}
299:
300: //{{{ Inner classes
301:
302: //{{{ MouseHandler class
303: class MouseHandler extends MouseInputAdapter {
304: boolean selectAll;
305:
306: //{{{ mousePressed() method
307: public void mousePressed(MouseEvent evt) {
308: selectAll = (!hasFocus() && selectAllOnFocus);
309: } //}}}
310:
311: //{{{ mouseReleased() method
312: public void mouseReleased(MouseEvent evt) {
313: SwingUtilities.invokeLater(new Runnable() {
314: public void run() {
315: if (selectAll)
316: selectAll();
317: }
318: });
319: } //}}}
320:
321: //{{{ mouseMoved() method
322: public void mouseMoved(MouseEvent evt) {
323: Border border = getBorder();
324: Insets insets = border
325: .getBorderInsets(HistoryTextField.this );
326:
327: if (evt.getX() >= getWidth() - insets.right)
328: setCursor(Cursor.getDefaultCursor());
329: else
330: setCursor(Cursor
331: .getPredefinedCursor(Cursor.TEXT_CURSOR));
332: } //}}}
333:
334: //{{{ mouseDragged() method
335: public void mouseDragged(MouseEvent evt) {
336: selectAll = false;
337: } //}}}
338: } //}}}
339:
340: //{{{ HistoryBorder class
341: static class HistoryBorder extends AbstractBorder {
342: static final int WIDTH = 16;
343:
344: public void paintBorder(Component c, Graphics g, int x, int y,
345: int w, int h) {
346: g.translate(x + w - WIDTH, y - 1);
347:
348: //if(c.isEnabled())
349: //{
350: // // vertical separation line
351: // g.setColor(UIManager.getColor("controlDkShadow"));
352: // g.drawLine(0,0,0,h);
353: //}
354:
355: // down arrow
356: int w2 = WIDTH / 2;
357: int h2 = h / 2;
358: g
359: .setColor(UIManager
360: .getColor(c.isEnabled()
361: && ((HistoryTextField) c)
362: .getModel() != null ? "TextField.foreground"
363: : "TextField.disabledForeground"));
364: g.drawLine(w2 - 5, h2 - 2, w2 + 4, h2 - 2);
365: g.drawLine(w2 - 4, h2 - 1, w2 + 3, h2 - 1);
366: g.drawLine(w2 - 3, h2, w2 + 2, h2);
367: g.drawLine(w2 - 2, h2 + 1, w2 + 1, h2 + 1);
368: g.drawLine(w2 - 1, h2 + 2, w2, h2 + 2);
369:
370: g.translate(-(x + w - WIDTH), -(y - 1));
371: }
372:
373: public Insets getBorderInsets(Component c) {
374: return new Insets(0, 0, 0, WIDTH);
375: }
376: } //}}}
377:
378: //}}}
379: }
|