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;
}
}