001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.handlers;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.lang.reflect.Method;
014:
015: import org.eclipse.core.commands.ExecutionEvent;
016: import org.eclipse.core.commands.ExecutionException;
017: import org.eclipse.core.runtime.IConfigurationElement;
018: import org.eclipse.swt.SWT;
019: import org.eclipse.swt.graphics.Point;
020: import org.eclipse.swt.widgets.Composite;
021: import org.eclipse.swt.widgets.Control;
022: import org.eclipse.swt.widgets.Display;
023: import org.eclipse.ui.internal.ExceptionHandler;
024:
025: /**
026: * This handler is an adaptation of the widget method handler allowing select
027: * all to work even in some cases where the "selectAll" method does not exist.
028: * This handler attempts to use "getTextLimit" and "setSelection" to do select
029: * all. If this doesn't work, then it finally fails.
030: *
031: * @since 3.0
032: */
033: public class SelectAllHandler extends WidgetMethodHandler {
034:
035: /**
036: * The parameters for a single point select all.
037: */
038: private static final Class[] METHOD_PARAMETERS = { Point.class };
039:
040: public final Object execute(final ExecutionEvent event)
041: throws ExecutionException {
042: final Method methodToExecute = getMethodToExecute();
043: if (methodToExecute != null) {
044: try {
045: final Control focusControl = Display.getCurrent()
046: .getFocusControl();
047:
048: final int numParams = methodToExecute
049: .getParameterTypes().length;
050:
051: if ((focusControl instanceof Composite)
052: && ((((Composite) focusControl).getStyle() & SWT.EMBEDDED) != 0)) {
053:
054: // we only support selectAll for swing components
055: if (numParams != 0) {
056: return null;
057: }
058:
059: /*
060: * Okay. Have a seat. Relax a while. This is going to be a
061: * bumpy ride. If it is an embedded widget, then it *might*
062: * be a Swing widget. At the point where this handler is
063: * executing, the key event is already bound to be
064: * swallowed. If I don't do something, then the key will be
065: * gone for good. So, I will try to forward the event to the
066: * Swing widget. Unfortunately, we can't even count on the
067: * Swing libraries existing, so I need to use reflection
068: * everywhere. And, to top it off, I need to dispatch the
069: * event on the Swing event queue, which means that it will
070: * be carried out asynchronously to the SWT event queue.
071: */
072: try {
073: final Object focusComponent = getFocusComponent();
074: if (focusComponent != null) {
075: Runnable methodRunnable = new Runnable() {
076: public void run() {
077: try {
078: methodToExecute.invoke(
079: focusComponent, null);
080: // and back to the UI thread :-)
081: focusControl.getDisplay()
082: .asyncExec(
083: new Runnable() {
084: public void run() {
085: if (!focusControl
086: .isDisposed()) {
087: focusControl
088: .notifyListeners(
089: SWT.Selection,
090: null);
091: }
092: }
093: });
094: } catch (final IllegalAccessException e) {
095: // The method is protected, so do
096: // nothing.
097: } catch (final InvocationTargetException e) {
098: /*
099: * I would like to log this exception --
100: * and possibly show a dialog to the
101: * user -- but I have to go back to the
102: * SWT event loop to do this. So, back
103: * we go....
104: */
105: focusControl.getDisplay()
106: .asyncExec(
107: new Runnable() {
108: public void run() {
109: ExceptionHandler
110: .getInstance()
111: .handleException(
112: new ExecutionException(
113: "An exception occurred while executing " //$NON-NLS-1$
114: + methodToExecute
115: .getName(),
116: e
117: .getTargetException()));
118: }
119: });
120: }
121: }
122: };
123:
124: swingInvokeLater(methodRunnable);
125: }
126: } catch (final ClassNotFoundException e) {
127: // There is no Swing support, so do nothing.
128:
129: } catch (final NoSuchMethodException e) {
130: // The API has changed, which seems amazingly unlikely.
131: throw new Error(
132: "Something is seriously wrong here"); //$NON-NLS-1$
133: }
134: } else if (numParams == 0) {
135: // This is a no-argument selectAll method.
136: methodToExecute.invoke(focusControl, null);
137: focusControl.notifyListeners(SWT.Selection, null);
138:
139: } else if (numParams == 1) {
140: // This is a single-point selection method.
141: final Method textLimitAccessor = focusControl
142: .getClass().getMethod(
143: "getTextLimit", NO_PARAMETERS); //$NON-NLS-1$
144: final Integer textLimit = (Integer) textLimitAccessor
145: .invoke(focusControl, null);
146: final Object[] parameters = { new Point(0,
147: textLimit.intValue()) };
148: methodToExecute.invoke(focusControl, parameters);
149: focusControl.notifyListeners(SWT.Selection, null);
150:
151: } else {
152: /*
153: * This means that getMethodToExecute() has been changed,
154: * while this method hasn't.
155: */
156: throw new ExecutionException(
157: "Too many parameters on select all", new Exception()); //$NON-NLS-1$
158:
159: }
160:
161: } catch (IllegalAccessException e) {
162: // The method is protected, so do nothing.
163:
164: } catch (InvocationTargetException e) {
165: throw new ExecutionException(
166: "An exception occurred while executing " //$NON-NLS-1$
167: + getMethodToExecute(), e
168: .getTargetException());
169:
170: } catch (NoSuchMethodException e) {
171: // I can't get the text limit. Do nothing.
172:
173: }
174: }
175:
176: return null;
177: }
178:
179: /**
180: * Looks up the select all method on the given focus control.
181: *
182: * @return The method on the focus control; <code>null</code> if none.
183: */
184: protected Method getMethodToExecute() {
185: Method method = super .getMethodToExecute();
186:
187: // Let's see if we have a control that supports point-based selection.
188: if (method == null) {
189: final Control focusControl = Display.getCurrent()
190: .getFocusControl();
191: if (focusControl != null) {
192: try {
193: method = focusControl.getClass().getMethod(
194: "setSelection", //$NON-NLS-1$
195: METHOD_PARAMETERS);
196: } catch (NoSuchMethodException e) {
197: // Do nothing.
198: }
199: }
200: }
201:
202: return method;
203: }
204:
205: /**
206: * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
207: * java.lang.String, java.lang.Object)
208: */
209: public void setInitializationData(IConfigurationElement config,
210: String propertyName, Object data) {
211: // The name is always "selectAll".
212: methodName = "selectAll"; //$NON-NLS-1$
213: }
214: }
|