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  package org.xnap.gui.component;
20  
21  import java.awt.event.InputEvent;
22  import java.awt.event.KeyAdapter;
23  import java.awt.event.KeyEvent;
24  import java.awt.event.KeyListener;
25  
26  import javax.swing.KeyStroke;
27  import javax.swing.text.JTextComponent;
28  
29  import org.apache.log4j.Logger;
30  import org.xnap.XNap;
31  import org.xnap.gui.shortcut.DefaultShortcut;
32  import org.xnap.gui.shortcut.ShortcutManager;
33  
34  
35  /***
36   *
37   */
38  public class EmacsCompletionMode extends CompletionMode
39  {
40      
41  	private static DefaultShortcut forward = new DefaultShortcut
42  		(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK),
43  		 XNap.tr("Completion"), XNap.tr("Emacs Cycle Forward"), 
44  		 "emacsCycleForward");
45  	
46  	private static DefaultShortcut backward = new DefaultShortcut
47  		(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK),
48  		 XNap.tr("Completion"), XNap.tr("Emacs Cycle Backward"), 
49  		 "emacsCycleBackward");
50  
51      static {
52          ShortcutManager.getInstance().add(forward);
53  		ShortcutManager.getInstance().add(backward);
54      }
55  
56      private static Logger logger = Logger.getLogger(EmacsCompletionMode.class);
57      /***
58      * Holds the key listener used for receiving the mode's trigger key events.
59      */
60      private KeyListener listener = new KeyHandler();
61      /***
62       * The current set of possible completions for the input which can be
63       * traversed.
64       */
65      private Object[] matches = null;
66      /***
67       * The index of the currently shown completion.
68       */
69      private int index = 0;
70      /***
71       * The original string which triggered the completion.
72       */
73      private String orig = null;
74  
75      /***
76       * @param textComponent
77       * @param model
78       * @param wholeText
79       */
80      public EmacsCompletionMode(JTextComponent textComponent,
81                                 CompletionModel model, boolean wholeText)
82      {
83          super(textComponent, model, wholeText);
84      }
85  
86      /***
87       * @param textComponent
88       * @param wholeText
89       */
90      public EmacsCompletionMode(JTextComponent textComponent, boolean wholeText)
91      {
92          super(textComponent, wholeText);
93      }
94  
95      /***
96       * @param textComponent
97       * @param model
98       */
99      public EmacsCompletionMode(JTextComponent textComponent,
100                                CompletionModel model)
101     {
102         super(textComponent, model);
103     }
104 
105     /***
106      * @param textComponent
107      */
108     public EmacsCompletionMode(JTextComponent textComponent)
109     {
110         super(textComponent);
111     }
112 
113     /*
114      * @see org.xnap.gui.component.CompletionMode#getName()
115      */
116     public String getName()
117     {
118         return XNap.tr("Emacs Completion");
119     }
120 
121     protected void disable()
122     {
123         getTextComponent().removeKeyListener(listener);
124     }
125 
126     protected void enable()
127     {
128         getTextComponent().addKeyListener(listener);
129     }
130 
131     private Object[] getMatches()
132     {
133         int size = getModel().getSize();
134         Object[] matches = new Object[size];
135 
136         for (int i = 0; i < size; i++) {
137             matches[i] = getModel().getElementAt(i);
138         }
139 
140         return matches;
141     }
142 
143     private class KeyHandler extends KeyAdapter
144     {
145         public void keyPressed(KeyEvent e)
146         {
147             if (forward.getKeyStroke() != null 
148 				&& forward.getKeyStroke().equals
149 				(KeyStroke.getKeyStrokeForEvent(e))) {
150                 // scroll forwards
151                 if (matches != null) {
152                     if ((index + 1) == matches.length) {
153                         setText(orig);
154                         getTextComponent().getToolkit().beep();
155                         matches = null;
156                     }
157                     else {
158                         setText(matches[++index].toString());
159                     }
160                 }
161                 else if (getModel().complete(getText())) {
162                     orig = getText();
163                     matches = getMatches();
164                     index = 0;
165                     setText(matches[0].toString());
166                 }
167                 e.consume();
168             }
169             else if (backward.getKeyStroke() != null 
170 					 && backward.getKeyStroke().equals
171 					 (KeyStroke.getKeyStrokeForEvent(e))) {
172 				// scroll backwards
173 				if (matches != null) {
174 					if (index > 0) {
175 						setText(matches[--index].toString());
176 					}
177 					else {
178 						setText(orig);
179 						matches = null;
180 					}
181 				}
182 				e.consume();
183 			}
184 			else if (e.getKeyCode() != KeyEvent.VK_ALT 
185 					 && e.getKeyCode() != KeyEvent.VK_CONTROL
186 					 && e.getKeyCode() != KeyEvent.VK_SHIFT
187 					 && e.getKeyCode() != KeyEvent.VK_META) {
188 				matches = null;
189 			}
190 		}
191     }
192 }