KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 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
12 package org.eclipse.ui.internal;
13
14 import org.eclipse.core.commands.AbstractHandler;
15 import org.eclipse.core.commands.ExecutionEvent;
16 import org.eclipse.core.commands.ExecutionException;
17 import org.eclipse.core.commands.ParameterizedCommand;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IConfigurationElement;
20 import org.eclipse.core.runtime.IExecutableExtension;
21 import org.eclipse.jface.bindings.Trigger;
22 import org.eclipse.jface.bindings.TriggerSequence;
23 import org.eclipse.jface.bindings.keys.KeyStroke;
24 import org.eclipse.jface.bindings.keys.SWTKeySupport;
25 import org.eclipse.jface.preference.IPreferenceStore;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.events.FocusEvent;
28 import org.eclipse.swt.events.FocusListener;
29 import org.eclipse.swt.events.KeyEvent;
30 import org.eclipse.swt.events.KeyListener;
31 import org.eclipse.swt.events.MouseEvent;
32 import org.eclipse.swt.events.MouseListener;
33 import org.eclipse.swt.events.TraverseEvent;
34 import org.eclipse.swt.events.TraverseListener;
35 import org.eclipse.swt.graphics.Rectangle;
36 import org.eclipse.swt.layout.FillLayout;
37 import org.eclipse.swt.widgets.Display;
38 import org.eclipse.swt.widgets.Shell;
39 import org.eclipse.swt.widgets.Table;
40 import org.eclipse.swt.widgets.TableColumn;
41 import org.eclipse.swt.widgets.TableItem;
42 import org.eclipse.ui.IEditorReference;
43 import org.eclipse.ui.IPerspectiveDescriptor;
44 import org.eclipse.ui.IWorkbenchPage;
45 import org.eclipse.ui.IWorkbenchPart;
46 import org.eclipse.ui.IWorkbenchPartReference;
47 import org.eclipse.ui.IWorkbenchWindow;
48 import org.eclipse.ui.contexts.IContextService;
49 import org.eclipse.ui.handlers.HandlerUtil;
50 import org.eclipse.ui.keys.IBindingService;
51
52 /**
53  * Its a base class for switching between views/editors/perspectives.
54  *
55  * @since 3.3
56  *
57  */

58
59 public abstract class CycleBaseHandler extends AbstractHandler implements
60         IExecutableExtension {
61     private Object JavaDoc selection;
62     protected IWorkbenchWindow window;
63     // true to go to next and false to go to previous part
64
protected boolean gotoDirection;
65     protected IWorkbenchPart activePart;
66     /**
67      * The list of key bindings for the backward command when it is open. This
68      * value is <code>null</code> if the dialog is not open.
69      */

70     private TriggerSequence[] backwardTriggerSequences = null;
71
72     protected ParameterizedCommand commandBackward = null;
73
74     protected ParameterizedCommand commandForward = null;
75     /**
76      * The list of key bindings for the forward command when it is open. This
77      * value is <code>null</code> if the dialog is not open.
78      */

79     private TriggerSequence[] forwardTriggerSequences = null;
80
81     /*
82      * (non-Javadoc)
83      *
84      * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
85      */

86
87     /**
88      * Add all items to the dialog in the activation order
89      */

90     protected abstract void addItems(Table table, WorkbenchPage page);
91
92     /**
93      * Get the backward command.
94      */

95     protected abstract ParameterizedCommand getBackwardCommand();
96
97     /**
98      * Get the forward command.
99      */

100     protected abstract ParameterizedCommand getForwardCommand();
101
102     public Object JavaDoc execute(ExecutionEvent event) throws ExecutionException {
103         window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
104
105         IWorkbenchPage page = window.getActivePage();
106         activePart = page.getActivePart();
107         openDialog((WorkbenchPage) page);
108         activate(page, selection);
109
110         return null;
111     }
112
113     /*
114      * Open a dialog showing all views in the activation order
115      */

116     protected void openDialog(WorkbenchPage page) {
117         final int MAX_ITEMS = 22;
118
119         selection = null;
120         final Shell dialog = new Shell(window.getShell(), SWT.MODELESS);
121         Display display = dialog.getDisplay();
122         dialog.setLayout(new FillLayout());
123
124         final Table table = new Table(dialog, SWT.SINGLE | SWT.FULL_SELECTION);
125         table.setHeaderVisible(true);
126         table.setLinesVisible(true);
127         TableColumn tc = new TableColumn(table, SWT.NONE);
128         tc.setResizable(false);
129         tc.setText(getTableHeader());
130         addItems(table, page);
131         int tableItemCount = table.getItemCount();
132
133         switch (tableItemCount) {
134         case 0:
135             // do nothing;
136
break;
137         case 1:
138             table.setSelection(0);
139             break;
140         default:
141             table.setSelection(gotoDirection ? 1 : table.getItemCount() - 1);
142         }
143
144         tc.pack();
145         table.pack();
146         dialog.pack();
147
148         Rectangle tableBounds = table.getBounds();
149         tableBounds.height = Math.min(tableBounds.height, table.getItemHeight()
150                 * MAX_ITEMS);
151         table.setBounds(tableBounds);
152
153         dialog.setBounds(dialog.computeTrim(tableBounds.x, tableBounds.y,
154                 tableBounds.width, tableBounds.height));
155
156         tc.setWidth(table.getClientArea().width);
157         table.setFocus();
158         table.addFocusListener(new FocusListener() {
159             public void focusGained(FocusEvent e) {
160                 // Do nothing
161
}
162
163             public void focusLost(FocusEvent e) {
164                 cancel(dialog);
165             }
166         });
167
168         Rectangle dialogBounds = dialog.getBounds();
169         Rectangle parentBounds = dialog.getParent().getBounds();
170
171         // the bounds of the monitor that contains the currently active part.
172
Rectangle monitorBounds = activePart == null ? display
173                 .getPrimaryMonitor().getBounds() : ((PartSite) activePart
174                 .getSite()).getPane().getControl().getMonitor().getBounds();
175
176         // Place it in the center of its parent;
177
dialogBounds.x = parentBounds.x
178                 + ((parentBounds.width - dialogBounds.width) / 2);
179         dialogBounds.y = parentBounds.y
180                 + ((parentBounds.height - dialogBounds.height) / 2);
181         if (!monitorBounds.contains(dialogBounds.x, dialogBounds.y)
182                 || !monitorBounds.contains(dialogBounds.x + dialogBounds.width,
183                         dialogBounds.y + dialogBounds.height)) {
184             // Place it in the center of the monitor if it is not visible
185
// when placed in the center of its parent;
186
dialogBounds.x = monitorBounds.x
187                     + (monitorBounds.width - dialogBounds.width) / 2;
188             dialogBounds.y = monitorBounds.y
189                     + (monitorBounds.height - dialogBounds.height) / 2;
190         }
191
192         dialog.setLocation(dialogBounds.x, dialogBounds.y);
193
194         /*
195          * Fetch the key bindings for the forward and backward commands. They
196          * will not change while the dialog is open, but the context will. Bug
197          * 55581.
198          */

199         commandForward = getForwardCommand();
200         commandBackward = getBackwardCommand();
201         /*
202          * Fetch the key bindings for the forward and backward commands. They
203          * will not change while the dialog is open, but the context will. Bug
204          * 55581.
205          */

206         final IBindingService bindingService = (IBindingService) window
207                 .getWorkbench().getService(IBindingService.class);
208         forwardTriggerSequences = bindingService
209                 .getActiveBindingsFor(commandForward);
210         backwardTriggerSequences = bindingService
211                 .getActiveBindingsFor(commandBackward);
212
213         final IContextService contextService = (IContextService) window
214                 .getWorkbench().getService(IContextService.class);
215         try {
216             dialog.open();
217             addMouseListener(table, dialog);
218             contextService.registerShell(dialog, IContextService.TYPE_NONE);
219             addKeyListener(table, dialog);
220             addTraverseListener(table);
221
222             while (!dialog.isDisposed()) {
223                 if (!display.readAndDispatch()) {
224                     display.sleep();
225                 }
226             }
227         } finally {
228             if (!dialog.isDisposed()) {
229                 cancel(dialog);
230             }
231             contextService.unregisterShell(dialog);
232             forwardTriggerSequences = null;
233             backwardTriggerSequences = null;
234         }
235     }
236
237     protected void addKeyListener(final Table table, final Shell dialog) {
238         table.addKeyListener(new KeyListener() {
239             private boolean firstKey = true;
240
241             private boolean quickReleaseMode = false;
242
243             public void keyPressed(KeyEvent e) {
244                 int keyCode = e.keyCode;
245                 char character = e.character;
246                 int accelerator = SWTKeySupport
247                         .convertEventToUnmodifiedAccelerator(e);
248                 KeyStroke keyStroke = SWTKeySupport
249                         .convertAcceleratorToKeyStroke(accelerator);
250
251                 boolean acceleratorForward = false;
252                 boolean acceleratorBackward = false;
253
254                 if (commandForward != null) {
255                     if (forwardTriggerSequences != null) {
256                         final int forwardCount = forwardTriggerSequences.length;
257                         for (int i = 0; i < forwardCount; i++) {
258                             final TriggerSequence triggerSequence = forwardTriggerSequences[i];
259
260                             // Compare the last key stroke of the binding.
261
final Trigger[] triggers = triggerSequence
262                                     .getTriggers();
263                             final int triggersLength = triggers.length;
264                             if ((triggersLength > 0)
265                                     && (triggers[triggersLength - 1]
266                                             .equals(keyStroke))) {
267                                 acceleratorForward = true;
268                                 break;
269                             }
270                         }
271                     }
272                 }
273
274                 if (commandBackward != null) {
275                     if (backwardTriggerSequences != null) {
276                         final int backwardCount = backwardTriggerSequences.length;
277                         for (int i = 0; i < backwardCount; i++) {
278                             final TriggerSequence triggerSequence = backwardTriggerSequences[i];
279
280                             // Compare the last key stroke of the binding.
281
final Trigger[] triggers = triggerSequence
282                                     .getTriggers();
283                             final int triggersLength = triggers.length;
284                             if ((triggersLength > 0)
285                                     && (triggers[triggersLength - 1]
286                                             .equals(keyStroke))) {
287                                 acceleratorBackward = true;
288                                 break;
289                             }
290                         }
291                     }
292                 }
293
294                 if (character == SWT.CR || character == SWT.LF) {
295                     ok(dialog, table);
296                 } else if (acceleratorForward) {
297                     if (firstKey && e.stateMask != 0) {
298                         quickReleaseMode = true;
299                     }
300
301                     int index = table.getSelectionIndex();
302                     table.setSelection((index + 1) % table.getItemCount());
303                 } else if (acceleratorBackward) {
304                     if (firstKey && e.stateMask != 0) {
305                         quickReleaseMode = true;
306                     }
307
308                     int index = table.getSelectionIndex();
309                     table.setSelection(index >= 1 ? index - 1 : table
310                             .getItemCount() - 1);
311                 } else if (keyCode != SWT.ALT && keyCode != SWT.COMMAND
312                         && keyCode != SWT.CTRL && keyCode != SWT.SHIFT
313                         && keyCode != SWT.ARROW_DOWN && keyCode != SWT.ARROW_UP
314                         && keyCode != SWT.ARROW_LEFT
315                         && keyCode != SWT.ARROW_RIGHT) {
316                     cancel(dialog);
317                 }
318
319                 firstKey = false;
320             }
321
322             public void keyReleased(KeyEvent e) {
323                 int keyCode = e.keyCode;
324                 int stateMask = e.stateMask;
325
326                 final IPreferenceStore store = WorkbenchPlugin.getDefault()
327                         .getPreferenceStore();
328                 final boolean stickyCycle = store
329                         .getBoolean(IPreferenceConstants.STICKY_CYCLE);
330                 if ((!stickyCycle && (firstKey || quickReleaseMode))
331                         && keyCode == stateMask) {
332                     ok(dialog, table);
333                 }
334             }
335         });
336     }
337
338     /**
339      * Adds a listener to the given table that blocks all traversal operations.
340      *
341      * @param table
342      * The table to which the traversal suppression should be added;
343      * must not be <code>null</code>.
344      */

345     protected final void addTraverseListener(final Table table) {
346         table.addTraverseListener(new TraverseListener() {
347             /**
348              * Blocks all key traversal events.
349              *
350              * @param event
351              * The trigger event; must not be <code>null</code>.
352              */

353             public final void keyTraversed(final TraverseEvent event) {
354                 event.doit = false;
355             }
356         });
357     }
358
359     /**
360      * Activate the selected item.
361      *
362      * @param page
363      * the page
364      * @param selectedItem
365      * the selected item
366      */

367     protected void activate(IWorkbenchPage page, Object JavaDoc selectedItem) {
368         if (selectedItem != null) {
369             if (selectedItem instanceof IEditorReference) {
370                 page.setEditorAreaVisible(true);
371             }
372             if (selectedItem instanceof IWorkbenchPartReference) {
373                 IWorkbenchPart part = ((IWorkbenchPartReference) selectedItem)
374                         .getPart(true);
375                 if (part != null) {
376                     page.activate(part);
377                 }
378             }
379             
380             if (selectedItem instanceof IPerspectiveDescriptor){
381                 IPerspectiveDescriptor persp = (IPerspectiveDescriptor) selectedItem;
382                 page.setPerspective(persp);
383             }
384
385         }
386     }
387
388     /*
389      * Close the dialog and set selection to null.
390      */

391     protected void cancel(Shell dialog) {
392         selection = null;
393         dialog.close();
394     }
395
396     /*
397      * Close the dialog saving the selection
398      */

399     protected void ok(Shell dialog, final Table table) {
400         TableItem[] items = table.getSelection();
401
402         if (items != null && items.length == 1) {
403             selection = items[0].getData();
404         }
405
406         dialog.close();
407     }
408
409     /*
410      * Add mouse listener to the table closing it when the mouse is pressed.
411      */

412     protected void addMouseListener(final Table table, final Shell dialog) {
413         table.addMouseListener(new MouseListener() {
414             public void mouseDoubleClick(MouseEvent e) {
415                 ok(dialog, table);
416             }
417
418             public void mouseDown(MouseEvent e) {
419                 ok(dialog, table);
420             }
421
422             public void mouseUp(MouseEvent e) {
423                 ok(dialog, table);
424             }
425         });
426     }
427
428     protected abstract String JavaDoc getTableHeader();
429
430     // return WorkbenchMessages.CyclePartAction_header;
431

432     public Object JavaDoc getSelection() {
433         return selection;
434     }
435
436     public IWorkbenchWindow getWindow() {
437         return window;
438     }
439
440     public TriggerSequence[] getBackwardTriggerSequences() {
441         return backwardTriggerSequences;
442     }
443
444     public TriggerSequence[] getForwardTriggerSequences() {
445         return forwardTriggerSequences;
446     }
447
448     /*
449      * (non-Javadoc)
450      *
451      * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
452      * java.lang.String, java.lang.Object)
453      */

454     public void setInitializationData(IConfigurationElement config,
455             String JavaDoc propertyName, Object JavaDoc data) throws CoreException {
456         gotoDirection = "true".equals(data); //$NON-NLS-1$
457
}
458 }
459
Popular Tags