KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > CyclePartAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.ui.internal;
12
13 import org.eclipse.core.commands.Command;
14 import org.eclipse.core.commands.ParameterizedCommand;
15 import org.eclipse.jface.action.Action;
16 import org.eclipse.jface.bindings.Trigger;
17 import org.eclipse.jface.bindings.TriggerSequence;
18 import org.eclipse.jface.bindings.keys.KeyStroke;
19 import org.eclipse.jface.bindings.keys.SWTKeySupport;
20 import org.eclipse.jface.preference.IPreferenceStore;
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.events.FocusEvent;
23 import org.eclipse.swt.events.FocusListener;
24 import org.eclipse.swt.events.HelpEvent;
25 import org.eclipse.swt.events.HelpListener;
26 import org.eclipse.swt.events.KeyEvent;
27 import org.eclipse.swt.events.KeyListener;
28 import org.eclipse.swt.events.MouseEvent;
29 import org.eclipse.swt.events.MouseListener;
30 import org.eclipse.swt.events.TraverseEvent;
31 import org.eclipse.swt.events.TraverseListener;
32 import org.eclipse.swt.graphics.Rectangle;
33 import org.eclipse.swt.layout.FillLayout;
34 import org.eclipse.swt.widgets.Display;
35 import org.eclipse.swt.widgets.Event;
36 import org.eclipse.swt.widgets.Shell;
37 import org.eclipse.swt.widgets.Table;
38 import org.eclipse.swt.widgets.TableColumn;
39 import org.eclipse.swt.widgets.TableItem;
40 import org.eclipse.ui.IEditorReference;
41 import org.eclipse.ui.IWorkbenchPage;
42 import org.eclipse.ui.IWorkbenchPart;
43 import org.eclipse.ui.IWorkbenchPartReference;
44 import org.eclipse.ui.IWorkbenchWindow;
45 import org.eclipse.ui.PlatformUI;
46 import org.eclipse.ui.commands.ICommandService;
47 import org.eclipse.ui.contexts.IContextService;
48 import org.eclipse.ui.keys.IBindingService;
49
50 /**
51  * Implements a action to enable the user switch between parts using keyboard.
52  */

53 public class CyclePartAction extends PageEventAction {
54
55     /**
56      * The list of key bindings for the backward command when it is open. This
57      * value is <code>null</code> if the dialog is not open.
58      */

59     private TriggerSequence[] backwardTriggerSequences = null;
60
61     private ParameterizedCommand commandBackward = null;
62
63     private ParameterizedCommand commandForward = null;
64
65     protected boolean forward;
66
67     /**
68      * The list of key bindings for the forward command when it is open. This
69      * value is <code>null</code> if the dialog is not open.
70      */

71     private TriggerSequence[] forwardTriggerSequences = null;
72
73     private Object JavaDoc selection;
74
75     /**
76      * Creates a CyclePartAction.
77      *
78      * @param window
79      * The workbench window on which the dialog should be created.
80      * @param next
81      * Whether the action is to move to the next part (as opposed to
82      * the previous).
83      */

84     public CyclePartAction(IWorkbenchWindow window, boolean next) {
85         super("", window); //$NON-NLS-1$
86
forward = next;
87         setText();
88         updateState();
89     }
90
91     /**
92      * Activate the selected item.
93      *
94      * @param page
95      * the page
96      * @param selectedItem
97      * the selected item
98      */

99     public void activate(IWorkbenchPage page, Object JavaDoc selectedItem) {
100         if (selectedItem != null) {
101             if (selectedItem instanceof IEditorReference) {
102                 page.setEditorAreaVisible(true);
103             }
104
105             IWorkbenchPart part = ((IWorkbenchPartReference) selectedItem)
106                     .getPart(true);
107
108             if (part != null) {
109                 page.activate(part);
110             }
111         }
112     }
113
114     /**
115      * Add all views to the dialog in the activation order
116      */

117     protected void addItems(Table table, WorkbenchPage page) {
118         IWorkbenchPartReference refs[] = page.getSortedParts();
119         boolean includeEditor = true;
120
121         for (int i = refs.length - 1; i >= 0; i--) {
122             if (refs[i] instanceof IEditorReference) {
123                 if (includeEditor) {
124                     IEditorReference activeEditor = (IEditorReference) refs[i];
125                     TableItem item = new TableItem(table, SWT.NONE);
126                     item.setText(WorkbenchMessages.CyclePartAction_editor);
127                     item.setImage(activeEditor.getTitleImage());
128                     item.setData(activeEditor);
129                     includeEditor = false;
130                 }
131             } else {
132                 TableItem item = new TableItem(table, SWT.NONE);
133                 item.setText(refs[i].getTitle());
134                 item.setImage(refs[i].getTitleImage());
135                 item.setData(refs[i]);
136             }
137         }
138     }
139
140     private void addKeyListener(final Table table, final Shell dialog) {
141         table.addKeyListener(new KeyListener() {
142             private boolean firstKey = true;
143
144             private boolean quickReleaseMode = false;
145
146             public void keyPressed(KeyEvent e) {
147                 int keyCode = e.keyCode;
148                 char character = e.character;
149                 int accelerator = SWTKeySupport
150                         .convertEventToUnmodifiedAccelerator(e);
151                 KeyStroke keyStroke = SWTKeySupport
152                         .convertAcceleratorToKeyStroke(accelerator);
153
154                 // System.out.println("\nPRESSED");
155
// printKeyEvent(e);
156
// System.out.println("accelerat:\t" + accelerator + "\t (" +
157
// KeySupport.formatStroke(Stroke.create(accelerator), true) +
158
// ")");
159

160                 boolean acceleratorForward = false;
161                 boolean acceleratorBackward = false;
162
163                 if (commandForward != null) {
164                     if (forwardTriggerSequences != null) {
165                         final int forwardCount = forwardTriggerSequences.length;
166                         for (int i = 0; i < forwardCount; i++) {
167                             final TriggerSequence triggerSequence = forwardTriggerSequences[i];
168
169                             // Compare the last key stroke of the binding.
170
final Trigger[] triggers = triggerSequence
171                                     .getTriggers();
172                             final int triggersLength = triggers.length;
173                             if ((triggersLength > 0)
174                                     && (triggers[triggersLength - 1]
175                                             .equals(keyStroke))) {
176                                 acceleratorForward = true;
177                                 break;
178                             }
179                         }
180                     }
181                 }
182
183                 if (commandBackward != null) {
184                     if (backwardTriggerSequences != null) {
185                         final int backwardCount = backwardTriggerSequences.length;
186                         for (int i = 0; i < backwardCount; i++) {
187                             final TriggerSequence triggerSequence = backwardTriggerSequences[i];
188
189                             // Compare the last key stroke of the binding.
190
final Trigger[] triggers = triggerSequence
191                                     .getTriggers();
192                             final int triggersLength = triggers.length;
193                             if ((triggersLength > 0)
194                                     && (triggers[triggersLength - 1]
195                                             .equals(keyStroke))) {
196                                 acceleratorBackward = true;
197                                 break;
198                             }
199                         }
200                     }
201                 }
202
203                 if (character == SWT.CR || character == SWT.LF) {
204                     ok(dialog, table);
205                 } else if (acceleratorForward) {
206                     if (firstKey && e.stateMask != 0) {
207                         quickReleaseMode = true;
208                     }
209
210                     int index = table.getSelectionIndex();
211                     table.setSelection((index + 1) % table.getItemCount());
212                 } else if (acceleratorBackward) {
213                     if (firstKey && e.stateMask != 0) {
214                         quickReleaseMode = true;
215                     }
216
217                     int index = table.getSelectionIndex();
218                     table.setSelection(index >= 1 ? index - 1 : table
219                             .getItemCount() - 1);
220                 } else if (keyCode != SWT.ALT && keyCode != SWT.COMMAND
221                         && keyCode != SWT.CTRL && keyCode != SWT.SHIFT
222                         && keyCode != SWT.ARROW_DOWN && keyCode != SWT.ARROW_UP
223                         && keyCode != SWT.ARROW_LEFT
224                         && keyCode != SWT.ARROW_RIGHT) {
225                     cancel(dialog);
226                 }
227
228                 firstKey = false;
229             }
230
231             public void keyReleased(KeyEvent e) {
232                 int keyCode = e.keyCode;
233                 int stateMask = e.stateMask;
234                 // char character = e.character;
235
// int accelerator = stateMask | (keyCode != 0 ? keyCode :
236
// convertCharacter(character));
237

238                 // System.out.println("\nRELEASED");
239
// printKeyEvent(e);
240
// System.out.println("accelerat:\t" + accelerator + "\t (" +
241
// KeySupport.formatStroke(Stroke.create(accelerator), true) +
242
// ")");
243

244                 final IPreferenceStore store = WorkbenchPlugin.getDefault()
245                         .getPreferenceStore();
246                 final boolean stickyCycle = store
247                         .getBoolean(IPreferenceConstants.STICKY_CYCLE);
248                 if ((!stickyCycle && (firstKey || quickReleaseMode))
249                         && keyCode == stateMask) {
250                     ok(dialog, table);
251                 }
252             }
253         });
254     }
255
256     /*
257      * Add mouse listener to the table closing it when the mouse is pressed.
258      */

259     private void addMouseListener(final Table table, final Shell dialog) {
260         table.addMouseListener(new MouseListener() {
261             public void mouseDoubleClick(MouseEvent e) {
262                 ok(dialog, table);
263             }
264
265             public void mouseDown(MouseEvent e) {
266                 ok(dialog, table);
267             }
268
269             public void mouseUp(MouseEvent e) {
270                 ok(dialog, table);
271             }
272         });
273     }
274
275     /**
276      * Adds a listener to the given table that blocks all traversal operations.
277      *
278      * @param table
279      * The table to which the traversal suppression should be added;
280      * must not be <code>null</code>.
281      */

282     private final void addTraverseListener(final Table table) {
283         table.addTraverseListener(new TraverseListener() {
284             /**
285              * Blocks all key traversal events.
286              *
287              * @param event
288              * The trigger event; must not be <code>null</code>.
289              */

290             public final void keyTraversed(final TraverseEvent event) {
291                 event.doit = false;
292             }
293         });
294     }
295
296     /*
297      * Close the dialog and set selection to null.
298      */

299     private void cancel(Shell dialog) {
300         selection = null;
301         dialog.close();
302     }
303
304     /**
305      * Return the backward action.
306      *
307      * @return the backward action
308      */

309     public String JavaDoc getBackwardActionDefinitionId() {
310         return commandBackward.getCommand().getId();
311     }
312
313     /**
314      * Return the forward action.
315      *
316      * @return the forward action
317      */

318     public String JavaDoc getForwardActionDefinitionId() {
319         return commandForward.getCommand().getId();
320     }
321
322     /**
323      * Returns the string which will be shown in the table header.
324      */

325     protected String JavaDoc getTableHeader() {
326         return WorkbenchMessages.CyclePartAction_header;
327     }
328
329     // private static void printKeyEvent(KeyEvent keyEvent) {
330
// System.out.println("keyCode:\t" + keyEvent.keyCode + "\t (" +
331
// KeySupport.formatStroke(Stroke.create(keyEvent.keyCode), true) + ")");
332
// System.out.println("stateMask:\t" + keyEvent.stateMask + "\t (" +
333
// KeySupport.formatStroke(Stroke.create(keyEvent.stateMask), true) + ")");
334
// System.out.println("character:\t" + (int) keyEvent.character + "\t (" +
335
// keyEvent.character + ")");
336
// }
337

338     /*
339      * Close the dialog saving the selection
340      */

341     private void ok(Shell dialog, final Table table) {
342         TableItem[] items = table.getSelection();
343
344         if (items != null && items.length == 1) {
345             selection = items[0].getData();
346         }
347
348         dialog.close();
349     }
350
351     /*
352      * Open a dialog showing all views in the activation order
353      */

354     private void openDialog(WorkbenchPage page) {
355         final int MAX_ITEMS = 22;
356
357         selection = null;
358         final Shell dialog = new Shell(getWorkbenchWindow().getShell(),
359                 SWT.MODELESS);
360         Display display = dialog.getDisplay();
361         dialog.setLayout(new FillLayout());
362
363         final Table table = new Table(dialog, SWT.SINGLE | SWT.FULL_SELECTION);
364         table.setHeaderVisible(true);
365         table.setLinesVisible(true);
366         TableColumn tc = new TableColumn(table, SWT.NONE);
367         tc.setResizable(false);
368         tc.setText(getTableHeader());
369         addItems(table, page);
370         int tableItemCount = table.getItemCount();
371
372         switch (tableItemCount) {
373         case 0:
374             // do nothing;
375
break;
376         case 1:
377             table.setSelection(0);
378             break;
379         default:
380             table.setSelection(forward ? 1 : table.getItemCount() - 1);
381         }
382
383         tc.pack();
384         table.pack();
385         dialog.pack();
386
387         Rectangle tableBounds = table.getBounds();
388         tableBounds.height = Math.min(tableBounds.height, table.getItemHeight()
389                 * MAX_ITEMS);
390         table.setBounds(tableBounds);
391
392         dialog.setBounds(dialog.computeTrim(tableBounds.x, tableBounds.y,
393                 tableBounds.width, tableBounds.height));
394
395         tc.setWidth(table.getClientArea().width);
396         table.setFocus();
397         table.addFocusListener(new FocusListener() {
398             public void focusGained(FocusEvent e) {
399                 // Do nothing
400
}
401
402             public void focusLost(FocusEvent e) {
403                 cancel(dialog);
404             }
405         });
406
407         Rectangle dialogBounds = dialog.getBounds();
408         Rectangle displayBounds = display.getClientArea();
409         Rectangle parentBounds = dialog.getParent().getBounds();
410
411         // Place it in the center of its parent;
412
dialogBounds.x = parentBounds.x
413                 + ((parentBounds.width - dialogBounds.width) / 2);
414         dialogBounds.y = parentBounds.y
415                 + ((parentBounds.height - dialogBounds.height) / 2);
416         if (!displayBounds.contains(dialogBounds.x, dialogBounds.y)
417                 || !displayBounds.contains(dialogBounds.x + dialogBounds.width,
418                         dialogBounds.y + dialogBounds.height)) {
419             // Place it in the center of the display if it is not visible
420
// when placed in the center of its parent;
421
dialogBounds.x = (displayBounds.width - dialogBounds.width) / 2;
422             dialogBounds.y = (displayBounds.height - dialogBounds.height) / 2;
423         }
424
425         dialog.setLocation(dialogBounds.x, dialogBounds.y);
426
427         table.removeHelpListener(getHelpListener());
428         table.addHelpListener(new HelpListener() {
429             public void helpRequested(HelpEvent event) {
430                 // Do nothing
431
}
432         });
433
434         /*
435          * Fetch the key bindings for the forward and backward commands. They
436          * will not change while the dialog is open, but the context will. Bug
437          * 55581.
438          */

439         final IBindingService bindingService = (IBindingService) PlatformUI
440                 .getWorkbench().getAdapter(IBindingService.class);
441         forwardTriggerSequences = bindingService
442                 .getActiveBindingsFor(commandForward);
443         backwardTriggerSequences = bindingService
444                 .getActiveBindingsFor(commandBackward);
445
446         final IContextService contextService = (IContextService) page
447                 .getWorkbenchWindow().getWorkbench().getAdapter(
448                         IContextService.class);
449         try {
450             dialog.open();
451             addMouseListener(table, dialog);
452             contextService.registerShell(dialog,
453                     IContextService.TYPE_NONE);
454             addKeyListener(table, dialog);
455             addTraverseListener(table);
456
457             while (!dialog.isDisposed()) {
458                 if (!display.readAndDispatch()) {
459                     display.sleep();
460                 }
461             }
462         } finally {
463             if (!dialog.isDisposed()) {
464                 cancel(dialog);
465             }
466             contextService.unregisterShell(dialog);
467             forwardTriggerSequences = null;
468             backwardTriggerSequences = null;
469         }
470     }
471
472     /**
473      * See IPageListener
474      */

475     public void pageActivated(IWorkbenchPage page) {
476         super.pageActivated(page);
477         updateState();
478     }
479
480     /**
481      * See IPageListener
482      */

483     public void pageClosed(IWorkbenchPage page) {
484         super.pageClosed(page);
485         updateState();
486     }
487
488     /**
489      * See IPartListener
490      */

491     public void partClosed(IWorkbenchPart part) {
492         super.partClosed(part);
493         updateState();
494     }
495
496     /**
497      * See IPartListener
498      */

499     public void partOpened(IWorkbenchPart part) {
500         super.partOpened(part);
501         updateState();
502     }
503
504     /**
505      * @see Action#run()
506      */

507     public void runWithEvent(Event e) {
508         if (getWorkbenchWindow() == null) {
509             // action has been disposed
510
return;
511         }
512         IWorkbenchPage page = getActivePage();
513         openDialog((WorkbenchPage) page);
514         activate(page, selection);
515     }
516
517     /**
518      * Set the backward action.
519      *
520      * @param actionDefinitionId
521      * the action
522      */

523     public void setBackwardActionDefinitionId(String JavaDoc actionDefinitionId) {
524         final ICommandService commandService = (ICommandService) getWorkbenchWindow()
525                 .getWorkbench().getAdapter(ICommandService.class);
526         final Command command = commandService.getCommand(actionDefinitionId);
527         commandBackward = new ParameterizedCommand(command, null);
528     }
529
530     /**
531      * Set the forward action.
532      *
533      * @param actionDefinitionId
534      * the action
535      */

536     public void setForwardActionDefinitionId(String JavaDoc actionDefinitionId) {
537         final ICommandService commandService = (ICommandService) getWorkbenchWindow()
538                 .getWorkbench().getAdapter(ICommandService.class);
539         final Command command = commandService.getCommand(actionDefinitionId);
540         commandForward = new ParameterizedCommand(command, null);
541     }
542
543     /**
544      * Set text and tooltips in the action.
545      */

546     protected void setText() {
547         // TBD: Remove text and tooltip when this becomes an invisible action.
548
if (forward) {
549             setText(WorkbenchMessages.CyclePartAction_next_text);
550             setToolTipText(WorkbenchMessages.CyclePartAction_next_toolTip);
551             // @issue missing action ids
552
getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(this,
553                     IWorkbenchHelpContextIds.CYCLE_PART_FORWARD_ACTION);
554             setActionDefinitionId("org.eclipse.ui.window.nextView"); //$NON-NLS-1$
555
} else {
556             setText(WorkbenchMessages.CyclePartAction_prev_text);
557             setToolTipText(WorkbenchMessages.CyclePartAction_prev_toolTip);
558             // @issue missing action ids
559
getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(this,
560                     IWorkbenchHelpContextIds.CYCLE_PART_BACKWARD_ACTION);
561             setActionDefinitionId("org.eclipse.ui.window.previousView"); //$NON-NLS-1$
562
}
563     }
564
565     /**
566      * Updates the enabled state.
567      */

568     protected void updateState() {
569         IWorkbenchPage page = getActivePage();
570         if (page == null) {
571             setEnabled(false);
572             return;
573         }
574         // enable iff there is at least one other part to switch to
575
// (the editor area counts as one entry)
576
int count = page.getViewReferences().length;
577         if (page.getEditorReferences().length > 0) {
578             ++count;
579         }
580         setEnabled(count >= 1);
581     }
582
583 }
584
Popular Tags