Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/gui/InputHandler.java


1   /*
2    * InputHandler.java - Manages key bindings and executes actions
3    * :tabSize=8:indentSize=8:noTabs=false:
4    * :folding=explicit:collapseFolds=1:
5    *
6    * Copyright (C) 1999, 2003 Slava Pestov
7    *
8    * This program is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License
10   * as published by the Free Software Foundation; either version 2
11   * of the License, or any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   *
18   * You should have received a copy of the GNU General Public License
19   * along with this program; if not, write to the Free Software
20   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21   */
22  
23  package org.gjt.sp.jedit.gui;
24  
25  //{{{ Imports
26  import javax.swing.JOptionPane;
27  import org.gjt.sp.jedit.textarea.JEditTextArea;
28  import org.gjt.sp.jedit.*;
29  //}}}
30  
31  /**
32   * An input handler converts the user's key strokes into concrete actions.
33   * It also takes care of macro recording and action repetition.<p>
34   *
35   * This class provides all the necessary support code for an input
36   * handler, but doesn't actually do any key binding logic. It is up
37   * to the implementations of this class to do so.
38   *
39   * @author Slava Pestov
40   * @version $Id: InputHandler.java,v 1.20 2003/08/28 22:05:24 spestov Exp $
41   * @see org.gjt.sp.jedit.gui.DefaultInputHandler
42   */
43  public abstract class InputHandler
44  {
45    //{{{ InputHandler constructor
46    /**
47     * Creates a new input handler.
48     * @param view The view
49     */
50    public InputHandler(View view)
51    {
52      this.view = view;
53      repeatCount = 1;
54    } //}}}
55  
56    //{{{ addKeyBinding() method
57    /**
58     * Adds a key binding to this input handler.
59     * @param keyBinding The key binding (the format of this is
60     * input-handler specific)
61     * @param action The action
62     */
63    public abstract void addKeyBinding(String keyBinding, String action);
64    //}}}
65  
66    //{{{ addKeyBinding() method
67    /**
68     * Adds a key binding to this input handler.
69     * @param keyBinding The key binding (the format of this is
70     * input-handler specific)
71     * @param action The action
72     */
73    public abstract void addKeyBinding(String keyBinding, EditAction action);
74    //}}}
75  
76    //{{{ removeKeyBinding() method
77    /**
78     * Removes a key binding from this input handler.
79     * @param keyBinding The key binding
80     */
81    public abstract void removeKeyBinding(String keyBinding);
82    //}}}
83  
84    //{{{ removeAllKeyBindings() method
85    /**
86     * Removes all key bindings from this input handler.
87     */
88    public abstract void removeAllKeyBindings();
89    //}}}
90  
91    //{{{ isPrefixActive() method
92    /**
93     * Returns if a prefix key has been pressed.
94     */
95    public boolean isPrefixActive()
96    {
97      return false;
98    } //}}}
99  
100   //{{{ handleKey() method
101   /**
102    * Handles a keystroke.
103    * @param keyStroke The key stroke.
104    * @since jEdit 4.2pre5
105    */
106   public abstract boolean handleKey(KeyEventTranslator.Key keyStroke);
107   //}}}
108 
109   //{{{ getRepeatCount() method
110   /**
111    * Returns the number of times the next action will be repeated.
112    */
113   public int getRepeatCount()
114   {
115     return repeatCount;
116   } //}}}
117 
118   //{{{ setRepeatCount() method
119   /**
120    * Sets the number of times the next action will be repeated.
121    * @param repeatCount The repeat count
122    */
123   public void setRepeatCount(int repeatCount)
124   {
125     int oldRepeatCount = this.repeatCount;
126     this.repeatCount = repeatCount;
127     if(oldRepeatCount != repeatCount)
128       view.getStatus().setMessage(null);
129   } //}}}
130 
131   //{{{ getLastAction() method
132   /**
133    * Returns the last executed action.
134    * @since jEdit 2.5pre5
135    */
136   public EditAction getLastAction()
137   {
138     return lastAction;
139   } //}}}
140 
141   //{{{ getLastActionCount() method
142   /**
143    * Returns the number of times the last action was executed.
144    * @since jEdit 2.5pre5
145    */
146   public int getLastActionCount()
147   {
148     return lastActionCount;
149   } //}}}
150 
151   //{{{ readNextChar() method
152   /**
153    * Invokes the specified BeanShell code, replacing __char__ in the
154    * code with the next input character.
155    * @param msg The prompt to display in the status bar
156    * @param code The code
157    * @since jEdit 3.2pre2
158    */
159   public void readNextChar(String msg, String code)
160   {
161     view.getStatus().setMessage(msg);
162     readNextChar = code;
163   } //}}}
164 
165   //{{{ readNextChar() method
166   /**
167    * @deprecated Use the other form of this method instead
168    */
169   public void readNextChar(String code)
170   {
171     readNextChar = code;
172   } //}}}
173 
174   //{{{ resetLastActionCount() method
175   /**
176    * Resets the last action count. This should be called when an
177    * editing operation that is not an action is invoked, for example
178    * a mouse click.
179    * @since jEdit 4.0pre1
180    */
181   public void resetLastActionCount()
182   {
183     lastActionCount = 0;
184   } //}}}
185 
186   //{{{ invokeAction() method
187   /**
188    * Invokes the specified action, repeating and recording it as
189    * necessary.
190    * @param action The action
191    * @since jEdit 4.2pre1
192    */
193   public void invokeAction(String action)
194   {
195     invokeAction(jEdit.getAction(action));
196   } //}}}
197 
198   //{{{ invokeAction() method
199   /**
200    * Invokes the specified action, repeating and recording it as
201    * necessary.
202    * @param action The action
203    */
204   public void invokeAction(EditAction action)
205   {
206     Buffer buffer = view.getBuffer();
207 
208     /* if(buffer.insideCompoundEdit())
209       buffer.endCompoundEdit(); */
210 
211     // remember the last executed action
212     if(!action.noRememberLast())
213     {
214       HistoryModel.getModel("action").addItem(action.getName());
215       if(lastAction == action)
216         lastActionCount++;
217       else
218       {
219         lastAction = action;
220         lastActionCount = 1;
221       }
222     }
223 
224     // remember old values, in case action changes them
225     int _repeatCount = repeatCount;
226 
227     // execute the action
228     if(action.noRepeat() || _repeatCount == 1)
229       action.invoke(view);
230     else
231     {
232       // stop people doing dumb stuff like C+ENTER 100 C+n
233       if(_repeatCount > REPEAT_COUNT_THRESHOLD)
234       {
235         String label = action.getLabel();
236         if(label == null)
237           label = action.getName();
238         else
239           label = GUIUtilities.prettifyMenuLabel(label);
240 
241         Object[] pp = { label, new Integer(_repeatCount) };
242 
243         if(GUIUtilities.confirm(view,"large-repeat-count",pp,
244           JOptionPane.WARNING_MESSAGE,
245           JOptionPane.YES_NO_OPTION)
246           != JOptionPane.YES_OPTION)
247         {
248           repeatCount = 1;
249           view.getStatus().setMessage(null);
250           return;
251         }
252       }
253 
254       try
255       {
256         buffer.beginCompoundEdit();
257 
258         for(int i = 0; i < _repeatCount; i++)
259           action.invoke(view);
260       }
261       finally
262       {
263         buffer.endCompoundEdit();
264       }
265     }
266 
267     Macros.Recorder recorder = view.getMacroRecorder();
268 
269     if(recorder != null && !action.noRecord())
270       recorder.record(_repeatCount,action.getCode());
271 
272     // If repeat was true originally, clear it
273     // Otherwise it might have been set by the action, etc
274     if(_repeatCount != 1)
275     {
276       // first of all, if this action set a
277       // readNextChar, do not clear the repeat
278       if(readNextChar != null)
279         return;
280 
281       repeatCount = 1;
282       view.getStatus().setMessage(null);
283     }
284   } //}}}
285 
286   //{{{ invokeLastAction() method
287   public void invokeLastAction()
288   {
289     if(lastAction == null)
290       view.getToolkit().beep();
291     else
292       invokeAction(lastAction);
293   } //}}}
294 
295   //{{{ Protected members
296   private static final int REPEAT_COUNT_THRESHOLD = 20;
297 
298   //{{{ Instance variables
299   protected View view;
300   protected int repeatCount;
301 
302   protected EditAction lastAction;
303   protected int lastActionCount;
304 
305   protected String readNextChar;
306   //}}}
307 
308   //{{{ userInput() method
309   protected void userInput(char ch)
310   {
311     lastActionCount = 0;
312 
313     JEditTextArea textArea = view.getTextArea();
314 
315     /* Buffer buffer = view.getBuffer();
316     if(!buffer.insideCompoundEdit())
317       buffer.beginCompoundEdit(); */
318 
319     if(repeatCount == 1)
320       textArea.userInput(ch);
321     else
322     {
323       // stop people doing dumb stuff like C+ENTER 100 C+n
324       if(repeatCount > REPEAT_COUNT_THRESHOLD)
325       {
326         Object[] pp = { String.valueOf(ch),
327           new Integer(repeatCount) };
328 
329         if(GUIUtilities.confirm(view,
330           "large-repeat-count.user-input",pp,
331           JOptionPane.WARNING_MESSAGE,
332           JOptionPane.YES_NO_OPTION)
333           != JOptionPane.YES_OPTION)
334         {
335           repeatCount = 1;
336           view.getStatus().setMessage(null);
337           return;
338         }
339       }
340 
341       Buffer buffer = view.getBuffer();
342       try
343       {
344         if(repeatCount != 1)
345           buffer.beginCompoundEdit();
346         for(int i = 0; i < repeatCount; i++)
347           textArea.userInput(ch);
348       }
349       finally
350       {
351         if(repeatCount != 1)
352           buffer.endCompoundEdit();
353       }
354     }
355 
356     Macros.Recorder recorder = view.getMacroRecorder();
357 
358     if(recorder != null)
359     {
360       recorder.recordInput(repeatCount,ch,
361         textArea.isOverwriteEnabled());
362     }
363 
364     repeatCount = 1;
365   } //}}}
366 
367   //{{{ invokeReadNextChar() method
368   protected void invokeReadNextChar(char ch)
369   {
370     Buffer buffer = view.getBuffer();
371 
372     /* if(buffer.insideCompoundEdit())
373       buffer.endCompoundEdit(); */
374 
375     String charStr = MiscUtilities.charsToEscapes(String.valueOf(ch));
376 
377     // this might be a bit slow if __char__ occurs a lot
378     int index;
379     while((index = readNextChar.indexOf("__char__")) != -1)
380     {
381       readNextChar = readNextChar.substring(0,index)
382         + '\'' + charStr + '\''
383         + readNextChar.substring(index + 8);
384     }
385 
386     Macros.Recorder recorder = view.getMacroRecorder();
387     if(recorder != null)
388       recorder.record(getRepeatCount(),readNextChar);
389 
390     if(getRepeatCount() != 1)
391     {
392       try
393       {
394         buffer.beginCompoundEdit();
395 
396         BeanShell.eval(view,BeanShell.getNameSpace(),
397           "for(int i = 1; i < "
398           + getRepeatCount() + "; i++)\n{\n"
399           + readNextChar + "\n}");
400       }
401       finally
402       {
403         buffer.endCompoundEdit();
404       }
405     }
406     else
407       BeanShell.eval(view,BeanShell.getNameSpace(),readNextChar);
408 
409     readNextChar = null;
410 
411     view.getStatus().setMessage(null);
412   } //}}}
413 
414   //}}}
415 }