001: /*
002: * HistoryText.java - Common code for text components with a history
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2004 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.text.*;
028: import javax.swing.event.MouseInputAdapter;
029: import java.awt.*;
030: import java.awt.event.*;
031: import org.gjt.sp.jedit.*;
032:
033: //}}}
034:
035: /**
036: * Controller (manager of models) for HistoryTextArea.
037: * @author Slava Pestov
038: * @version $Id: HistoryText.java 8899 2007-02-05 23:33:10Z ezust $
039: */
040: public class HistoryText {
041: //{{{ HistoryText constructor
042: public HistoryText(JTextComponent text, String name) {
043: this .text = text;
044: setModel(name);
045: index = -1;
046: } //}}}
047:
048: //{{{ fireActionPerformed() method
049: public void fireActionPerformed() {
050: } //}}}
051:
052: //{{{ getIndex() mehtod
053: public int getIndex() {
054: return index;
055: } //}}}
056:
057: //{{{ setIndex() mehtod
058: public void setIndex(int index) {
059: this .index = index;
060: } //}}}
061:
062: //{{{ getModel() method
063: /**
064: * Returns the underlying history controller.
065: * @since jEdit 4.3pre1
066: */
067: public HistoryModel getModel() {
068: return historyModel;
069: } //}}}
070:
071: //{{{ setModel() method
072: /**
073: * Sets the history list controller.
074: * @param name The model name
075: * @since jEdit 4.3pre1
076: */
077: public void setModel(String name) {
078: if (name == null)
079: historyModel = null;
080: else
081: historyModel = HistoryModel.getModel(name);
082: index = -1;
083: } //}}}
084:
085: //{{{ setInstantPopups() method
086: /**
087: * Sets if selecting a value from the popup should immediately fire
088: * an ActionEvent.
089: */
090: public void setInstantPopups(boolean instantPopups) {
091: this .instantPopups = instantPopups;
092: } //}}}
093:
094: //{{{ getInstantPopups() method
095: /**
096: * Returns if selecting a value from the popup should immediately fire
097: * an ActionEvent.
098: */
099: public boolean getInstantPopups() {
100: return instantPopups;
101: } //}}}
102:
103: //{{{ addCurrentToHistory() method
104: /**
105: * Adds the currently entered item to the history.
106: */
107: public void addCurrentToHistory() {
108: if (historyModel != null)
109: historyModel.addItem(getText());
110: index = 0;
111: } //}}}
112:
113: //{{{ doBackwardSearch() method
114: public void doBackwardSearch() {
115: if (historyModel == null)
116: return;
117:
118: if (text.getSelectionEnd() != getDocument().getLength()) {
119: text.setCaretPosition(getDocument().getLength());
120: }
121:
122: int start = getInputStart();
123: String t = getText().substring(0,
124: text.getSelectionStart() - start);
125: if (t == null) {
126: historyPrevious();
127: return;
128: }
129:
130: for (int i = index + 1; i < historyModel.getSize(); i++) {
131: String item = historyModel.getItem(i);
132: if (item.startsWith(t)) {
133: text.replaceSelection(item.substring(t.length()));
134: text.select(getInputStart() + t.length(), getDocument()
135: .getLength());
136: index = i;
137: return;
138: }
139: }
140:
141: text.getToolkit().beep();
142: } //}}}
143:
144: //{{{ doForwardSearch() method
145: public void doForwardSearch() {
146: if (historyModel == null)
147: return;
148:
149: if (text.getSelectionEnd() != getDocument().getLength()) {
150: text.setCaretPosition(getDocument().getLength());
151: }
152:
153: int start = getInputStart();
154: String t = getText().substring(0,
155: text.getSelectionStart() - start);
156: if (t == null) {
157: historyNext();
158: return;
159: }
160:
161: for (int i = index - 1; i >= 0; i--) {
162: String item = historyModel.getItem(i);
163: if (item.startsWith(t)) {
164: text.replaceSelection(item.substring(t.length()));
165: text.select(getInputStart() + t.length(), getDocument()
166: .getLength());
167: index = i;
168: return;
169: }
170: }
171:
172: text.getToolkit().beep();
173: } //}}}
174:
175: //{{{ historyPrevious() method
176: public void historyPrevious() {
177: if (historyModel == null)
178: return;
179:
180: if (index == historyModel.getSize() - 1)
181: text.getToolkit().beep();
182: else if (index == -1) {
183: current = getText();
184: setText(historyModel.getItem(0));
185: index = 0;
186: } else {
187: // have to do this because setText() sets index to -1
188: int newIndex = index + 1;
189: setText(historyModel.getItem(newIndex));
190: index = newIndex;
191: }
192: } //}}}
193:
194: //{{{ historyNext() method
195: public void historyNext() {
196: if (historyModel == null)
197: return;
198:
199: if (index == -1)
200: text.getToolkit().beep();
201: else if (index == 0)
202: setText(current);
203: else {
204: // have to do this because setText() sets index to -1
205: int newIndex = index - 1;
206: setText(historyModel.getItem(newIndex));
207: index = newIndex;
208: }
209: } //}}}
210:
211: //{{{ getDocument() method
212: public Document getDocument() {
213: return text.getDocument();
214: } //}}}
215:
216: //{{{ getText() method
217: /**
218: * Subclasses can override this to provide funky history behavior,
219: * for JTextPanes and such.
220: */
221: public String getText() {
222: return text.getText();
223: } //}}}
224:
225: //{{{ setText() method
226: /**
227: * Subclasses can override this to provide funky history behavior,
228: * for JTextPanes and such.
229: */
230: public void setText(String text) {
231: this .index = -1;
232: this .text.setText(text);
233: } //}}}
234:
235: //{{{ getInputStart() method
236: /**
237: * Subclasses can override this to provide funky history behavior,
238: * for JTextPanes and such.
239: */
240: public int getInputStart() {
241: return 0;
242: } //}}}
243:
244: //{{{ showPopupMenu() method
245: public void showPopupMenu(String t, int x, int y) {
246: if (historyModel == null)
247: return;
248:
249: text.requestFocus();
250:
251: if (popup != null && popup.isVisible()) {
252: popup.setVisible(false);
253: return;
254: }
255:
256: popup = new JPopupMenu();
257: JMenuItem caption = new JMenuItem(jEdit
258: .getProperty("history.caption"));
259: caption.getModel().setEnabled(false);
260: popup.add(caption);
261: popup.addSeparator();
262:
263: for (int i = 0; i < historyModel.getSize(); i++) {
264: String item = historyModel.getItem(i);
265: if (item.startsWith(t)) {
266: JMenuItem menuItem = new JMenuItem(item);
267: menuItem.setActionCommand(String.valueOf(i));
268: menuItem.addActionListener(new ActionHandler());
269: popup.add(menuItem);
270: }
271: }
272:
273: GUIUtilities.showPopupMenu(popup, text, x, y, false);
274: } //}}}
275:
276: //{{{ showPopupMenu() method
277: public void showPopupMenu(boolean search) {
278: if (search)
279: showPopupMenu(getText().substring(getInputStart(),
280: text.getSelectionStart()), 0, text.getHeight());
281: else
282: showPopupMenu("", 0, text.getHeight());
283: } //}}}
284:
285: //{{{ Private members
286: private JTextComponent text;
287: private HistoryModel historyModel;
288: private int index;
289: private String current;
290: private JPopupMenu popup;
291: private boolean instantPopups;
292:
293: //}}}
294:
295: //{{{ ActionHandler class
296: class ActionHandler implements ActionListener {
297: public void actionPerformed(ActionEvent evt) {
298: int ind = Integer.parseInt(evt.getActionCommand());
299: if (ind == -1) {
300: if (index != -1)
301: setText(current);
302: } else {
303: setText(historyModel.getItem(ind));
304: index = ind;
305: }
306: if (instantPopups) {
307: addCurrentToHistory();
308: fireActionPerformed();
309: }
310: }
311: } //}}}
312: }
|