KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > dialogs > TextFieldNavigationHandler


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.ui.dialogs;
12
13 import com.ibm.icu.text.BreakIterator;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.core.commands.Command;
20 import org.eclipse.core.commands.CommandManager;
21 import org.eclipse.core.commands.ParameterizedCommand;
22 import org.eclipse.core.commands.common.NotDefinedException;
23 import org.eclipse.core.commands.contexts.ContextManager;
24
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.custom.StyledText;
27 import org.eclipse.swt.events.DisposeEvent;
28 import org.eclipse.swt.events.DisposeListener;
29 import org.eclipse.swt.events.FocusEvent;
30 import org.eclipse.swt.events.FocusListener;
31 import org.eclipse.swt.events.KeyAdapter;
32 import org.eclipse.swt.events.KeyEvent;
33 import org.eclipse.swt.events.MouseAdapter;
34 import org.eclipse.swt.events.MouseEvent;
35 import org.eclipse.swt.graphics.Point;
36 import org.eclipse.swt.widgets.Combo;
37 import org.eclipse.swt.widgets.Control;
38 import org.eclipse.swt.widgets.Text;
39
40 import org.eclipse.jface.bindings.BindingManager;
41 import org.eclipse.jface.bindings.Scheme;
42 import org.eclipse.jface.bindings.TriggerSequence;
43 import org.eclipse.jface.bindings.keys.KeySequence;
44 import org.eclipse.jface.bindings.keys.SWTKeySupport;
45 import org.eclipse.jface.preference.IPreferenceStore;
46
47 import org.eclipse.ui.PlatformUI;
48 import org.eclipse.ui.commands.ICommandService;
49 import org.eclipse.ui.keys.IBindingService;
50 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
51
52 import org.eclipse.jdt.ui.PreferenceConstants;
53
54 import org.eclipse.jdt.internal.ui.JavaPlugin;
55 import org.eclipse.jdt.internal.ui.text.JavaWordIterator;
56
57 /**
58  * Support for camelCase-aware sub-word navigation in dialog fields.
59  */

60 public class TextFieldNavigationHandler {
61     
62     public static void install(Text text) {
63         if (isSubWordNavigationEnabled())
64             new FocusHandler(new TextNavigable(text));
65     }
66
67     public static void install(StyledText styledText) {
68         if (isSubWordNavigationEnabled())
69             new FocusHandler(new StyledTextNavigable(styledText));
70     }
71     
72     public static void install(Combo combo) {
73         if (isSubWordNavigationEnabled())
74             new FocusHandler(new ComboNavigable(combo));
75     }
76     
77     private static boolean isSubWordNavigationEnabled() {
78         IPreferenceStore preferenceStore= JavaPlugin.getDefault().getCombinedPreferenceStore();
79         return preferenceStore.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION);
80     }
81     
82     private abstract static class WorkaroundNavigable extends Navigable {
83         /* workarounds for:
84          * - bug 103630: Add API: Combo#getCaretPosition()
85          * - bug 106024: Text#setSelection(int, int) does not handle start > end with SWT.SINGLE
86          */

87         Point fLastSelection;
88         int fCaretPosition;
89         
90         void selectionChanged() {
91             Point selection= getSelection();
92             if (selection.equals(fLastSelection)) {
93                 // leave caret position
94
} else if (selection.x == selection.y) { //empty range
95
fCaretPosition= selection.x;
96             } else if (fLastSelection.y == selection.y) {
97                 fCaretPosition= selection.x; //same end -> assume caret at start
98
} else {
99                 fCaretPosition= selection.y;
100             }
101             fLastSelection= selection;
102         }
103     }
104     
105     private abstract static class Navigable {
106         public abstract Control getControl();
107         
108         public abstract String JavaDoc getText();
109
110         public abstract void setText(String JavaDoc text);
111         
112         public abstract Point getSelection();
113
114         public abstract void setSelection(int start, int end);
115         
116         public abstract int getCaretPosition();
117     }
118     
119     private static class TextNavigable extends WorkaroundNavigable {
120         static final boolean BUG_106024_TEXT_SELECTION=
121                 "win32".equals(SWT.getPlatform()) //$NON-NLS-1$
122
// on carbon, getCaretPosition() always returns getSelection().x
123
|| "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
124

125         private final Text fText;
126         
127         public TextNavigable(Text text) {
128             fText= text;
129             // workaround for bug 106024:
130
if (BUG_106024_TEXT_SELECTION) {
131                 fLastSelection= getSelection();
132                 fCaretPosition= fLastSelection.y;
133                 fText.addKeyListener(new KeyAdapter() {
134                     public void keyReleased(KeyEvent e) {
135                         selectionChanged();
136                     }
137                 });
138                 fText.addMouseListener(new MouseAdapter() {
139                     public void mouseUp(MouseEvent e) {
140                         selectionChanged();
141                     }
142                 });
143             }
144         }
145         
146         public Control getControl() {
147             return fText;
148         }
149
150         public String JavaDoc getText() {
151             return fText.getText();
152         }
153
154         public void setText(String JavaDoc text) {
155             fText.setText(text);
156         }
157         
158         public Point getSelection() {
159             return fText.getSelection();
160         }
161
162         public int getCaretPosition() {
163             if (BUG_106024_TEXT_SELECTION) {
164                 selectionChanged();
165                 return fCaretPosition;
166             } else {
167                 return fText.getCaretPosition();
168             }
169         }
170
171         public void setSelection(int start, int end) {
172             fText.setSelection(start, end);
173         }
174     }
175     
176     private static class StyledTextNavigable extends Navigable {
177         private final StyledText fStyledText;
178         
179         public StyledTextNavigable(StyledText styledText) {
180             fStyledText= styledText;
181         }
182         
183         public Control getControl() {
184             return fStyledText;
185         }
186         
187         public String JavaDoc getText() {
188             return fStyledText.getText();
189         }
190         
191         public void setText(String JavaDoc text) {
192             fStyledText.setText(text);
193         }
194         
195         public Point getSelection() {
196             return fStyledText.getSelection();
197         }
198         
199         public int getCaretPosition() {
200             return fStyledText.getCaretOffset();
201         }
202         
203         public void setSelection(int start, int end) {
204             fStyledText.setSelection(start, end);
205         }
206     }
207     
208     private static class ComboNavigable extends WorkaroundNavigable {
209         private final Combo fCombo;
210         
211         public ComboNavigable(Combo combo) {
212             fCombo= combo;
213             // workaround for bug 103630:
214
fLastSelection= getSelection();
215             fCaretPosition= fLastSelection.y;
216             fCombo.addKeyListener(new KeyAdapter() {
217                 public void keyReleased(KeyEvent e) {
218                     selectionChanged();
219                 }
220             });
221             fCombo.addMouseListener(new MouseAdapter() {
222                 public void mouseUp(MouseEvent e) {
223                     selectionChanged();
224                 }
225             });
226         }
227         
228         public Control getControl() {
229             return fCombo;
230         }
231
232         public String JavaDoc getText() {
233             return fCombo.getText();
234         }
235         
236         public void setText(String JavaDoc text) {
237             fCombo.setText(text);
238         }
239         
240         public Point getSelection() {
241             return fCombo.getSelection();
242         }
243         
244         public int getCaretPosition() {
245             selectionChanged();
246             return fCaretPosition;
247 // return fCombo.getCaretPosition(); // not available: bug 103630
248
}
249         
250         public void setSelection(int start, int end) {
251             fCombo.setSelection(new Point(start, end));
252         }
253     }
254     
255     private static class FocusHandler implements FocusListener {
256         
257         private static final String JavaDoc EMPTY_TEXT= ""; //$NON-NLS-1$
258

259         private final JavaWordIterator fIterator;
260         private final Navigable fNavigable;
261         private KeyAdapter fKeyListener;
262         
263         private FocusHandler(Navigable navigable) {
264             fIterator= new JavaWordIterator();
265             fNavigable= navigable;
266             
267             Control control= navigable.getControl();
268             control.addFocusListener(this);
269             if (control.isFocusControl())
270                 activate();
271             control.addDisposeListener(new DisposeListener() {
272                 public void widgetDisposed(DisposeEvent e) {
273                     deactivate();
274                 }
275             });
276         }
277
278         public void focusGained(FocusEvent e) {
279             activate();
280         }
281
282         public void focusLost(FocusEvent e) {
283             deactivate();
284         }
285
286         private void activate() {
287             fNavigable.getControl().addKeyListener(getKeyListener());
288         }
289         
290         private void deactivate() {
291             if (fKeyListener != null) {
292                 Control control= fNavigable.getControl();
293                 if (! control.isDisposed())
294                     control.removeKeyListener(fKeyListener);
295                 fKeyListener= null;
296             }
297         }
298         
299         private KeyAdapter getKeyListener() {
300             if (fKeyListener == null) {
301                 fKeyListener= new KeyAdapter() {
302                     private final boolean IS_WORKAROUND= (fNavigable instanceof ComboNavigable)
303                             || (fNavigable instanceof TextNavigable && TextNavigable.BUG_106024_TEXT_SELECTION);
304                     private List JavaDoc/*<Submission>*/ fSubmissions;
305
306                     public void keyPressed(KeyEvent e) {
307                         if (IS_WORKAROUND) {
308                             if (e.keyCode == SWT.ARROW_LEFT && e.stateMask == SWT.MOD2) {
309                                 int caretPosition= fNavigable.getCaretPosition();
310                                 if (caretPosition != 0) {
311                                     Point selection= fNavigable.getSelection();
312                                     if (caretPosition == selection.x)
313                                         fNavigable.setSelection(selection.y, caretPosition - 1);
314                                     else
315                                         fNavigable.setSelection(selection.x, caretPosition - 1);
316                                 }
317                                 e.doit= false;
318                                 return;
319                                 
320                             } else if (e.keyCode == SWT.ARROW_RIGHT && e.stateMask == SWT.MOD2) {
321                                 String JavaDoc text= fNavigable.getText();
322                                 int caretPosition= fNavigable.getCaretPosition();
323                                 if (caretPosition != text.length()) {
324                                     Point selection= fNavigable.getSelection();
325                                     if (caretPosition == selection.y)
326                                         fNavigable.setSelection(selection.x, caretPosition + 1);
327                                     else
328                                         fNavigable.setSelection(selection.y, caretPosition + 1);
329                                 }
330                                 e.doit= false;
331                                 return;
332                             }
333                         }
334                         int accelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
335                         KeySequence keySequence = KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke(accelerator));
336                         getSubmissions();
337                         for (Iterator iter= getSubmissions().iterator(); iter.hasNext();) {
338                             Submission submission= (Submission) iter.next();
339                             TriggerSequence[] triggerSequences= submission.getTriggerSequences();
340                             for (int i= 0; i < triggerSequences.length; i++) {
341                                 if (triggerSequences[i].equals(keySequence)) { // XXX does not work for multi-stroke bindings
342
e.doit= false;
343                                     submission.execute();
344                                     return;
345                                 }
346                             }
347                         }
348                     }
349                     
350                     private List JavaDoc/*<Submission>*/ getSubmissions() {
351                         if (fSubmissions != null)
352                             return fSubmissions;
353                         
354                         fSubmissions= new ArrayList JavaDoc();
355                         
356                         ICommandService commandService= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class);
357                         IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class);
358                         if (commandService == null || bindingService == null)
359                             return fSubmissions;
360                         
361                         // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=184502 ,
362
// similar to CodeAssistAdvancedConfigurationBlock.getKeyboardShortcut(..):
363
BindingManager localBindingManager= new BindingManager(new ContextManager(), new CommandManager());
364                         final Scheme[] definedSchemes= bindingService.getDefinedSchemes();
365                         if (definedSchemes != null) {
366                             try {
367                                 for (int i = 0; i < definedSchemes.length; i++) {
368                                     Scheme scheme= definedSchemes[i];
369                                     Scheme localSchemeCopy= localBindingManager.getScheme(scheme.getId());
370                                     localSchemeCopy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId());
371                                 }
372                             } catch (final NotDefinedException e) {
373                                 JavaPlugin.log(e);
374                             }
375                         }
376                         localBindingManager.setLocale(bindingService.getLocale());
377                         localBindingManager.setPlatform(bindingService.getPlatform());
378                         
379                         localBindingManager.setBindings(bindingService.getBindings());
380                         try {
381                             Scheme activeScheme= bindingService.getActiveScheme();
382                             if (activeScheme != null)
383                                 localBindingManager.setActiveScheme(activeScheme);
384                         } catch (NotDefinedException e) {
385                             JavaPlugin.log(e);
386                         }
387                         
388                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.SELECT_WORD_NEXT)) {
389                             public void execute() {
390                                 fIterator.setText(fNavigable.getText());
391                                 int caretPosition= fNavigable.getCaretPosition();
392                                 int newCaret= fIterator.following(caretPosition);
393                                 if (newCaret != BreakIterator.DONE) {
394                                     Point selection= fNavigable.getSelection();
395                                     if (caretPosition == selection.y)
396                                         fNavigable.setSelection(selection.x, newCaret);
397                                     else
398                                         fNavigable.setSelection(selection.y, newCaret);
399                                 }
400                                 fIterator.setText(EMPTY_TEXT);
401                             }
402                         });
403                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS)) {
404                             public void execute() {
405                                 fIterator.setText(fNavigable.getText());
406                                 int caretPosition= fNavigable.getCaretPosition();
407                                 int newCaret= fIterator.preceding(caretPosition);
408                                 if (newCaret != BreakIterator.DONE) {
409                                     Point selection= fNavigable.getSelection();
410                                     if (caretPosition == selection.x)
411                                         fNavigable.setSelection(selection.y, newCaret);
412                                     else
413                                         fNavigable.setSelection(selection.x, newCaret);
414                                 }
415                                 fIterator.setText(EMPTY_TEXT);
416                             }
417                         });
418                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.WORD_NEXT)) {
419                             public void execute() {
420                                 fIterator.setText(fNavigable.getText());
421                                 int caretPosition= fNavigable.getCaretPosition();
422                                 int newCaret= fIterator.following(caretPosition);
423                                 if (newCaret != BreakIterator.DONE)
424                                     fNavigable.setSelection(newCaret, newCaret);
425                                 fIterator.setText(EMPTY_TEXT);
426                             }
427                         });
428                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.WORD_PREVIOUS)) {
429                             public void execute() {
430                                 fIterator.setText(fNavigable.getText());
431                                 int caretPosition= fNavigable.getCaretPosition();
432                                 int newCaret= fIterator.preceding(caretPosition);
433                                 if (newCaret != BreakIterator.DONE)
434                                     fNavigable.setSelection(newCaret, newCaret);
435                                 fIterator.setText(EMPTY_TEXT);
436                             }
437                         });
438                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.DELETE_NEXT_WORD)) {
439                             public void execute() {
440                                 Point selection= fNavigable.getSelection();
441                                 String JavaDoc text= fNavigable.getText();
442                                 int start;
443                                 int end;
444                                 if (selection.x != selection.y) {
445                                     start= selection.x;
446                                     end= selection.y;
447                                 } else {
448                                     fIterator.setText(text);
449                                     start= fNavigable.getCaretPosition();
450                                     end= fIterator.following(start);
451                                     fIterator.setText(EMPTY_TEXT);
452                                     if (end == BreakIterator.DONE)
453                                         return;
454                                 }
455                                 fNavigable.setText(text.substring(0, start) + text.substring(end));
456                                 fNavigable.setSelection(start, start);
457                             }
458                         });
459                         fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD)) {
460                             public void execute() {
461                                 Point selection= fNavigable.getSelection();
462                                 String JavaDoc text= fNavigable.getText();
463                                 int start;
464                                 int end;
465                                 if (selection.x != selection.y) {
466                                     start= selection.x;
467                                     end= selection.y;
468                                 } else {
469                                     fIterator.setText(text);
470                                     end= fNavigable.getCaretPosition();
471                                     start= fIterator.preceding(end);
472                                     fIterator.setText(EMPTY_TEXT);
473                                     if (start == BreakIterator.DONE)
474                                         return;
475                                 }
476                                 fNavigable.setText(text.substring(0, start) + text.substring(end));
477                                 fNavigable.setSelection(start, start);
478                             }
479                         });
480                         
481                         return fSubmissions;
482                     }
483
484                     private TriggerSequence[] getKeyBindings(BindingManager localBindingManager, ICommandService commandService, String JavaDoc commandID) {
485                         Command command= commandService.getCommand(commandID);
486                         ParameterizedCommand pCmd= new ParameterizedCommand(command, null);
487                         return localBindingManager.getActiveBindingsDisregardingContextFor(pCmd);
488                     }
489                     
490                 };
491             }
492             return fKeyListener;
493         }
494     }
495     
496     private abstract static class Submission {
497         private TriggerSequence[] fTriggerSequences;
498         
499         public Submission(TriggerSequence[] triggerSequences) {
500             fTriggerSequences= triggerSequences;
501         }
502         
503         public TriggerSequence[] getTriggerSequences() {
504             return fTriggerSequences;
505         }
506         
507         public abstract void execute();
508     }
509     
510 }
511
Popular Tags