/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.rc.swing.listener; import java.awt.AWTEvent; import java.awt.Color; import java.awt.Component; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.SwingUtilities; import javax.swing.Timer; import org.eclipse.jubula.communication.internal.Communicator; import org.eclipse.jubula.communication.internal.message.ChangeAUTModeMessage; import org.eclipse.jubula.rc.common.AUTServer; import org.eclipse.jubula.rc.common.AUTServerConfiguration; import org.eclipse.jubula.rc.common.commands.ChangeAUTModeCommand; import org.eclipse.jubula.rc.common.exception.UnsupportedComponentException; import org.eclipse.jubula.rc.common.listener.AUTEventListener; import org.eclipse.jubula.rc.common.logger.AutServerLogger; import org.eclipse.jubula.rc.swing.tester.util.TesterUtil; import org.eclipse.jubula.tools.internal.exception.CommunicationException; /** * Abstract superclass for Listeners to be added to the AUT-Toolkit<br> * Listens to: <br> * AWTEvent.MOUSE_EVENT_MASK, <br> * AWTEvent.MOUSE_MOTION_EVENT_MASK, <br> * AWTEvent.KEY_EVENT_MASK <br> * The mouse event ENTERED, EXITED, moved and click are used to determine * the component under the mouse (the m_currentComponent). * * Known subclasses are: <br> * MappingListener, RecordListener, CheckListener * * @author BREDEX GmbH * @created 17.01.2006 */ public abstract class AbstractAutSwingEventListener extends BaseAWTEventListener implements IEventListener, AUTEventListener { /** * delay for high lighting in case of a mouse event PRESSED, RELEASED, which * may changes the appearances temporary, e.g. the 3D effect of JButton */ protected static final int REPAINT_DELAY = 5; /** the logger */ private static AutServerLogger log = new AutServerLogger(AbstractAutSwingEventListener.class); /** the event mask for the events this listener is interesting in*/ private static final long[] EVENT_MASK = new long[] { AWTEvent.MOUSE_EVENT_MASK, AWTEvent.MOUSE_MOTION_EVENT_MASK, AWTEvent.KEY_EVENT_MASK, AWTEvent.ITEM_EVENT_MASK, AWTEvent.ACTION_EVENT_MASK, AWTEvent.TEXT_EVENT_MASK, AWTEvent.FOCUS_EVENT_MASK, AWTEvent.COMPONENT_EVENT_MASK, AWTEvent.WINDOW_EVENT_MASK, AWTEvent.WINDOW_FOCUS_EVENT_MASK, AWTEvent.WINDOW_STATE_EVENT_MASK}; /** the lock object for m_currentComponent */ private Object m_componentLock = new Object(); /** * the component under the mouse, for top-level components this is a * Component and not a JComponent. */ private Component m_currentComponent = null; /** * the object deciding whether a KeyEvent is used for selecting a component * to the object map */ private KeyAcceptor m_acceptor = new KeyAcceptor(); /** * last event for not double firing events */ private AWTEvent m_lastEvent; /** Flag if m_currentComponent is highlighted or not*/ private boolean m_isHighLighted = false; /** * {@inheritDoc} */ public void eventDispatched(final AWTEvent event) { ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader()); handleEvent(event); } finally { Thread.currentThread().setContextClassLoader(oldCL); } } /** * Handles the given AWTEvent * @param event the event to handle. */ protected abstract void handleEvent(AWTEvent event); /** * This method is called by the AUTServer AFTER this instance is removed as * AWTEventListener for cleaning up purpose. <br> * * low lights the last hight lighted component. */ public void cleanUp() { // does not sychronize on component lock, because this method is called // after removing as AWTEventListener synchronized (m_componentLock) { if (getCurrentComponent() != null) { try { AUTServerConfiguration.getInstance() .getImplementationClass( getComponentClass( getCurrentComponent())); TesterUtil.lowLight(m_currentComponent); } catch (IllegalArgumentException iae) { log.error(iae); } catch (UnsupportedComponentException uce) { log.warn(uce); } } } } /** * change CheckModeState * @param mode int */ protected void changeCheckModeState(int mode) { ChangeAUTModeMessage msg = new ChangeAUTModeMessage(); msg.setMode(mode); msg.setMappingKey(AUTServerConfiguration.getInstance().getMappingKey()); msg.setMappingWithParentsKey(AUTServerConfiguration .getInstance().getMappingWithParentsKey()); msg.setMappingKeyModifier(AUTServerConfiguration .getInstance().getMappingKeyMod()); msg.setMappingWithParentsKeyModifier(AUTServerConfiguration .getInstance().getMappingWithParentsKeyMod()); msg.setKey2(AUTServerConfiguration.getInstance().getKey2()); msg.setKey2Modifier( AUTServerConfiguration.getInstance().getKey2Mod()); msg.setCheckModeKey(AUTServerConfiguration.getInstance() .getCheckModeKey()); msg.setCheckModeKeyModifier( AUTServerConfiguration.getInstance().getCheckModeKeyMod()); msg.setCheckCompKey(AUTServerConfiguration.getInstance() .getCheckCompKey()); msg.setCheckCompKeyModifier( AUTServerConfiguration.getInstance().getCheckCompKeyMod()); msg.setSingleLineTrigger( AUTServerConfiguration.getInstance().getSingleLineTrigger()); msg.setMultiLineTrigger( AUTServerConfiguration.getInstance().getMultiLineTrigger()); ChangeAUTModeCommand cmd = new ChangeAUTModeCommand(); cmd.setMessage(msg); try { Communicator clientCommunicator = AUTServer.getInstance().getCommunicator(); if (clientCommunicator != null && clientCommunicator.getConnection() != null) { AUTServer.getInstance().getCommunicator().send( cmd.execute()); } } catch (CommunicationException e) { e.printStackTrace(); } } /** * {@inheritDoc} */ public long[] getEventMask() { long[] eventMask = EVENT_MASK; // see findBugs return eventMask; } /** * @return Returns the lastEvent. */ protected AWTEvent getLastEvent() { return m_lastEvent; } /** * @param lastEvent The lastEvent to set. */ protected void setLastEvent(AWTEvent lastEvent) { m_lastEvent = lastEvent; } /** * @return Returns the componentLock. */ protected Object getComponentLock() { return m_componentLock; } /** * @return Returns the currentComponent. */ protected Component getCurrentComponent() { return m_currentComponent; } /** * @param currentComponent The currentComponent to set. */ protected void setCurrentComponent(Component currentComponent) { m_currentComponent = currentComponent; } /** * @return Returns the acceptor. */ protected KeyAcceptor getAcceptor() { return m_acceptor; } /** * Handles the High-/Lowlighting.<br> * When High-/LowLighting afer a click use highlightClicked. * @param source Component * @param implClass IImplementationClass * @param highlightColor highlight clolor */ protected void highlight(Component source, final Object implClass, final Color highlightColor) { synchronized (getComponentLock()) { if (getCurrentComponent() != null && getCurrentComponent() != source) { TesterUtil.lowLight(getCurrentComponent()); setHighLighted(false); } setCurrentComponent(source); Window windowAncestor = SwingUtilities.getWindowAncestor(getCurrentComponent()); if (windowAncestor != null && windowAncestor.getFocusOwner() != null) { try { AUTServerConfiguration.getInstance() .getImplementationClass( getComponentClass(getCurrentComponent())); TesterUtil.highLight(getCurrentComponent(), highlightColor); setHighLighted(true); } catch (IllegalArgumentException e) { log.error("unexpected exception", e); //$NON-NLS-1$ } catch (UnsupportedComponentException e) { /* This means that the component that we wish to highlight is * not supported. * The component will not be highlighted */ } } } } /** * Use this to handle the Highlighting after a Click. * @param implClass IImplementationClass * @param highlightColor highlight clolor */ protected void highlightClicked(final Object implClass, final Color highlightColor) { // start a thread, to hightligth AFTER the component, e.g. // JButton has processed the event and possible new painted Timer timer = new Timer(REPAINT_DELAY, new ActionListener() { public void actionPerformed(ActionEvent e) { synchronized (getComponentLock()) { if (getCurrentComponent() != null && getCurrentComponent().isShowing() && SwingUtilities.getWindowAncestor( getCurrentComponent()) != null && SwingUtilities.getWindowAncestor( getCurrentComponent()).getFocusOwner() != null) { try { AUTServerConfiguration.getInstance() .getImplementationClass( getComponentClass( getCurrentComponent())); TesterUtil.highLight( getCurrentComponent(), highlightColor); } catch (IllegalArgumentException iae) { log.error("unexpected exception", iae); //$NON-NLS-1$ } catch (UnsupportedComponentException uce) { /* This means that the component that we wish to highlight is * not supported. * The component will not be highlighted */ } } } } }); timer.setRepeats(false); timer.start(); } /** * Updates the highlighting * @param source Component * @param implClass IImplementationClass * @param highlightColor highlight color */ protected void updateHighlighting(Component source, final Object implClass, final Color highlightColor) { if (isHighLighted()) { highlight(source, implClass, highlightColor); } } /** * @return if the getCurrentComponent() is highlighted or not */ public boolean isHighLighted() { return m_isHighLighted; } /** * @param isHighLighted true for highlighted otherwise false. */ protected void setHighLighted(boolean isHighLighted) { m_isHighLighted = isHighLighted; } }