package com.lodh.administrator.rcp.commands; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Listener; /** * Handles the cut command in both dialogs and windows. This handler is enabled * if the focus control supports the "cut" method. * * @since 3.0 */ public class WidgetMethodHandler { /** * Track this base class enabled state. * * @since 3.4 */ private boolean baseEnabled = true; /** * The parameters to pass to the method this handler invokes. This handler * always passes no parameters. */ protected static final Class[] NO_PARAMETERS = new Class[0]; public WidgetMethodHandler() { } void updateEnablement() { boolean rc = isHandled(); if (rc != isEnabled()) { setBaseEnabled(rc); } } /** * The name of the method to be invoked by this handler. This value should * never be null. */ protected String methodName; private Listener focusListener; private Display display; /** * Invoke a runnable on the swing EDT. * * @param methodRunnable * @throws ClassNotFoundException * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException */ protected void swingInvokeLater(Runnable methodRunnable) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { final Class swingUtilitiesClass = Class.forName("javax.swing.SwingUtilities"); //$NON-NLS-1$ final Method swingUtilitiesInvokeLaterMethod = swingUtilitiesClass.getMethod("invokeLater", //$NON-NLS-1$ new Class[] { Runnable.class }); swingUtilitiesInvokeLaterMethod.invoke(swingUtilitiesClass, new Object[] { methodRunnable }); } /** * Find the swing focus component, if it is available. * * @return Hopefully, the swing focus component, but it can return * null. * @throws ClassNotFoundException * @throws NoSuchMethodException * @throws IllegalAccessException * @throws InvocationTargetException */ protected Object getFocusComponent() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { /* * Before JRE 1.4, one has to use * javax.swing.FocusManager.getCurrentManager().getFocusOwner(). Since * JRE 1.4, one has to use * java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager * ().getFocusOwner(); the use of the older API would install a * LegacyGlueFocusTraversalPolicy which causes endless recursions in * some situations. */ Class keyboardFocusManagerClass = null; try { keyboardFocusManagerClass = Class.forName("java.awt.KeyboardFocusManager"); //$NON-NLS-1$ } catch (ClassNotFoundException e) { // switch to the old guy } if (keyboardFocusManagerClass != null) { // Use JRE 1.4 API final Method keyboardFocusManagerGetCurrentKeyboardFocusManagerMethod = keyboardFocusManagerClass.getMethod( "getCurrentKeyboardFocusManager", null); //$NON-NLS-1$ final Object keyboardFocusManager = keyboardFocusManagerGetCurrentKeyboardFocusManagerMethod.invoke( keyboardFocusManagerClass, null); final Method keyboardFocusManagerGetFocusOwner = keyboardFocusManagerClass.getMethod("getFocusOwner", null); //$NON-NLS-1$ final Object focusComponent = keyboardFocusManagerGetFocusOwner.invoke(keyboardFocusManager, null); return focusComponent; } // Use JRE 1.3 API final Class focusManagerClass = Class.forName("javax.swing.FocusManager"); //$NON-NLS-1$ final Method focusManagerGetCurrentManagerMethod = focusManagerClass.getMethod("getCurrentManager", null); //$NON-NLS-1$ final Object focusManager = focusManagerGetCurrentManagerMethod.invoke(focusManagerClass, null); final Method focusManagerGetFocusOwner = focusManagerClass.getMethod("getFocusOwner", null); //$NON-NLS-1$ final Object focusComponent = focusManagerGetFocusOwner.invoke(focusManager, null); return focusComponent; } public final boolean isHandled() { return getMethodToExecute() != null; } /** * Looks up the method on the focus control. * * @return The method on the focus control; null if none. */ protected Method getMethodToExecute() { Display display = Display.getCurrent(); if (display == null) return null; final Control focusControl = display.getFocusControl(); Method method = null; if (focusControl != null) { final Class clazz = focusControl.getClass(); try { method = clazz.getMethod(methodName, NO_PARAMETERS); } catch (NoSuchMethodException e) { // Fall through... } } if ((method == null) && (focusControl instanceof Composite) && ((((Composite) focusControl).getStyle() & SWT.EMBEDDED) != 0)) { /* * We couldn't find the appropriate method on the current focus * control. It is possible that the current focus control is an * embedded SWT composite, which could be containing some Swing * components. If this is the case, then we should try to pass * through to the underlying Swing component hierarchy. Insha'allah, * this will work. */ try { final Object focusComponent = getFocusComponent(); if (focusComponent != null) { final Class clazz = focusComponent.getClass(); try { method = clazz.getMethod(methodName, NO_PARAMETERS); } catch (NoSuchMethodException e) { // Do nothing. } } } catch (final ClassNotFoundException e) { // There is no Swing support, so do nothing. } catch (final NoSuchMethodException e) { // The API has changed, which seems amazingly unlikely. throw new Error("Something is seriously wrong here"); //$NON-NLS-1$ } catch (IllegalAccessException e) { // The API has changed, which seems amazingly unlikely. throw new Error("Something is seriously wrong here"); //$NON-NLS-1$ } catch (InvocationTargetException e) { // The API has changed, which seems amazingly unlikely. throw new Error("Something is seriously wrong here"); //$NON-NLS-1$ } } return method; } /* * (non-Javadoc) * * @see org.eclipse.core.commands.AbstractHandler#dispose() */ public void dispose() { if (display != null && !display.isDisposed()) { display.removeFilter(SWT.FocusIn, focusListener); } display = null; focusListener = null; } /** * Whether this handler is capable of executing at this time. Subclasses may * override this method. If clients override this method they should also * consider overriding {@link #setEnabled(Object)} so they can be notified * about framework execution contexts. * * @return true * @see #setEnabled(Object) * @see #setBaseEnabled(boolean) */ public boolean isEnabled() { return baseEnabled; } /** * Allow the default {@link #isEnabled()} to answer our enabled state. It * will fire a HandlerEvent if necessary. If clients use this method they * should also consider overriding {@link #setEnabled(Object)} so they can * be notified about framework execution contexts. * * @param state * the enabled state * @since 3.4 */ protected void setBaseEnabled(boolean state) { if (baseEnabled == state) { return; } baseEnabled = state; } }