/******************************************************************************* * 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.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.JTree; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.basic.ComboPopup; import javax.swing.text.JTextComponent; import javax.swing.tree.TreePath; import org.eclipse.jubula.communication.internal.message.ChangeAUTModeMessage; import org.eclipse.jubula.rc.common.AUTServer; import org.eclipse.jubula.rc.common.exception.NoIdentifierForComponentException; import org.eclipse.jubula.rc.common.logger.AutServerLogger; import org.eclipse.jubula.tools.internal.objects.IComponentIdentifier; import org.eclipse.jubula.tools.internal.xml.businessmodell.Action; /** * The AWTEventListener for mode OBSERVATION. <br> * * The component is marked by calling the methods * highLight() and lowLight() respectively of the corresponding implementation * class. <br> * * The key events are tapped for selecting the <code>m_currentComponent</code> * to be used for the object mapping. The method <code>accept(KeyEvent)</code> * from the <code>MappingAcceptor</code> is queried to decide, whether the * event suits the active configuration. <br> * * A <code>ComponentHandler</code> is used to determine the identifaction of * the component. See the <code>ComponentHandler</code> for details. * * @author BREDEX GmbH * @created 23.08.2004 */ public class RecordListener extends AbstractAutSwingEventListener { /** the logger */ private static AutServerLogger log = new AutServerLogger( RecordListener.class); /** clicked or pressed Component */ private Component m_selectedComponent; /** clicked or pressed ComponentParent */ private Component m_selectedComponentParent; /** The RecordHelper */ private RecordHelper m_recordHelper = new RecordHelper(); /** The RecordActions */ private RecordActions m_recordActions = new RecordActions(); /** The RecordActions */ private int m_popupMouseBtn = MouseEvent.BUTTON3; /** ListSelectionListener */ private ListSelectionListener m_listSelListener = new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting() && AUTServer.getInstance().getMode() == ChangeAUTModeMessage.RECORD_MODE) { JList jlst = (JList)e.getSource(); IComponentIdentifier id = null; try { id = ComponentHandler.getIdentifier(jlst); if (jlst.getSelectedIndices().length != 0 && (getSelectedComponent() == jlst || getSelectedComponentParent() == jlst || getLastEvent().getSource() == jlst)) { Action a = m_recordHelper.compSysToAction( id, "CompSystem.SelectValues"); //$NON-NLS-1$ m_recordActions.selectListValues(jlst, id, a); //m_recordActions.setSelectionState(true); } } catch (NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } } }; /** TreeExpansionListener */ private TreeExpansionListener m_treExpListener = new TreeExpansionListener() { public void treeCollapsed(TreeExpansionEvent event) { JTree jtre = (JTree)event.getSource(); IComponentIdentifier id = null; TreePath path = event.getPath(); if (path != null && AUTServer.getInstance().getMode() == ChangeAUTModeMessage.RECORD_MODE && (getSelectedComponent() == jtre || getSelectedComponentParent() == jtre || getLastEvent().getSource() == jtre)) { try { id = ComponentHandler.getIdentifier(jtre); m_recordActions.collExpTree(jtre, path, id, "CompSystem.CollapseByTextPath"); //$NON-NLS-1$ //m_recordActions.setSelectionState(true); } catch (NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } } public void treeExpanded(TreeExpansionEvent event) { JTree jtre = (JTree)event.getSource(); IComponentIdentifier id = null; TreePath path = event.getPath(); if (path != null && AUTServer.getInstance().getMode() == ChangeAUTModeMessage.RECORD_MODE && (getSelectedComponent() == jtre || getSelectedComponentParent() == jtre || getLastEvent().getSource() == jtre)) { try { id = ComponentHandler.getIdentifier(jtre); m_recordActions.collExpTree(jtre, path, id, "CompSystem.ExpandByTextPath"); //$NON-NLS-1$ //m_recordActions.setSelectionState(true); } catch (NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } } }; /** TreeSelectionListener */ private TreeSelectionListener m_treSelListener = new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { JTree jtre = (JTree)e.getSource(); IComponentIdentifier id = null; TreePath path = e.getPath(); try { id = ComponentHandler.getIdentifier(jtre); if (path != null && AUTServer.getInstance().getMode() == ChangeAUTModeMessage.RECORD_MODE && (getSelectedComponent() == jtre || getSelectedComponentParent() == jtre || getLastEvent().getSource() == jtre)) { Action a = m_recordHelper.compSysToAction(id, "CompSystem.SelectByTextPath"); //$NON-NLS-1$ int clickcount = 1; //me.getClickCount(); m_recordActions.selectNode( jtre, path, id, a, clickcount); //m_recordActions.setSelectionState(true); } } catch (NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } }; /** ActionListener */ private ActionListener m_comboListener = new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("comboBoxChanged") //$NON-NLS-1$ && AUTServer.getInstance().getMode() == ChangeAUTModeMessage.RECORD_MODE) { Component popComp = null; Component lastSrc = getEventSource(getLastEvent()); if (lastSrc instanceof JList) { Component parent = lastSrc.getParent(); while (parent != null) { if (parent instanceof JPopupMenu) { JPopupMenu popUp = (JPopupMenu)parent; popComp = popUp.getInvoker(); if (popComp != null && popComp instanceof JComboBox) { lastSrc = popComp; } break; } parent = parent.getParent(); } } if (lastSrc instanceof JTextComponent) { Component parent = lastSrc.getParent(); if (parent instanceof JComboBox) { lastSrc = parent; } } if (e.getSource() instanceof JComboBox) { JComboBox jcbx = (JComboBox)e.getSource(); if (jcbx.getSelectedIndex() != -1 && (getSelectedComponent() == jcbx || getSelectedComponentParent() == jcbx || lastSrc == jcbx)) { IComponentIdentifier id = null; try { id = ComponentHandler.getIdentifier(jcbx); Action a = m_recordHelper.compSysToAction(id, "CompSystem.SelectValue"); //$NON-NLS-1$ m_recordActions.selectCbxValue(jcbx, id, a); m_recordActions.setSelectionState(true); } catch ( NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } } } } }; /** * method for event-handling * @param event AWTEvent */ protected void handleEvent(AWTEvent event) { if (event.equals(getLastEvent())) { return; } if (getEventSource(event) == null //|| isComboPopup(getEventSource(event)) || event.getID() == MouseEvent.MOUSE_EXITED) { return; } if (!(m_recordHelper.isSupportedComponent(getEventSource(event))) && !(event instanceof KeyEvent)) { return; } if ((event instanceof WindowEvent) || (event.getID() == ComponentEvent.COMPONENT_HIDDEN) || (event.getID() == ComponentEvent.COMPONENT_SHOWN)) { handleWindowEvent(event); } if ((event instanceof FocusEvent)) { handleFocusEvent(event); } if (event instanceof MouseEvent && getEventSource(event) instanceof JComponent) { handleMouseEvent(event, getEventSource(event)); } if ((event instanceof KeyEvent)) { setSelectedComponent(getEventSource(event)); setSelectedComponentParent(getEventSource(event).getParent()); KeyEvent keyEvent = (KeyEvent)event; handleKeyEvent(keyEvent); } if ((event.getID() == MouseEvent.MOUSE_ENTERED)) { setSelectedComponent(getEventSource(event)); setSelectedComponentParent(getEventSource(event).getParent()); handleMouseEnterEvent(getEventSource(event)); } if (event.getID() != MouseEvent.MOUSE_EXITED) { setLastEvent(event); } } /** * method for handling Mouse-Events * @param source Component */ protected void handleMouseEnterEvent(Component source) { if (source instanceof JList && !(isComboPopup(source))) { final JList jlst = (JList)source; boolean containsListener = false; ListSelectionListener[] lsls = jlst.getListSelectionListeners(); for (int i = 0; i < lsls.length; i++) { ListSelectionListener listener = lsls[i]; if (listener == m_listSelListener) { containsListener = true; } } if (!containsListener) { jlst.addListSelectionListener(m_listSelListener); } } else if (source instanceof JTree) { final JTree jtre = (JTree)source; boolean containsSelListener = false; TreeSelectionListener[] tsl = jtre.getTreeSelectionListeners(); for (int i = 0; i < tsl.length; i++) { TreeSelectionListener listener = tsl[i]; if (listener == m_treSelListener) { containsSelListener = true; } } if (!containsSelListener) { jtre.addTreeSelectionListener(m_treSelListener); } boolean containsExpListener = false; TreeExpansionListener[] tel = jtre.getTreeExpansionListeners(); for (int i = 0; i < tel.length; i++) { TreeExpansionListener listener = tel[i]; if (listener == m_treExpListener) { containsExpListener = true; } } if (!containsExpListener) { jtre.addTreeExpansionListener(m_treExpListener); } } else if (source instanceof JComboBox || source.getParent() instanceof JComboBox) { Component src = source; if (src.getParent() instanceof JComboBox) { src = source.getParent(); } final JComboBox jcbx = (JComboBox)src; boolean containsActionListener = false; ActionListener[] actL = jcbx.getActionListeners(); for (int i = 0; i < actL.length; i++) { ActionListener listener = actL[i]; if (listener == m_comboListener) { containsActionListener = true; } } if (!containsActionListener) { jcbx.addActionListener(m_comboListener); } } } /** * method for handling Mouse-Events * @param event AWTEvent * @param source Component */ protected void handleMouseEvent(AWTEvent event, Component source) { MouseEvent me = (MouseEvent)event; if (me.isPopupTrigger()) { m_popupMouseBtn = me.getButton(); m_recordActions.setPopupMouseButton(m_popupMouseBtn); } IComponentIdentifier id = null; try { id = ComponentHandler.getIdentifier(source); //don't capture right-click before ContextMenu (for Windows) if (getLastEvent() == null) { return; } if (getLastEvent().getID() == MouseEvent.MOUSE_RELEASED && !(me.getSource() instanceof JPopupMenu) && me.getButton() == m_popupMouseBtn) { m_recordActions.clickGraphComp(id, me, source); } if ((me.getID() == MouseEvent.MOUSE_RELEASED)) { //don't capture right-click before ContextMenu (for Linux) if (me.getButton() == m_popupMouseBtn && getLastEvent().getSource() instanceof JPopupMenu) { return; } if (source.getParent() instanceof JComboBox && source instanceof JButton) { return; } if (source.getParent() instanceof JComboBox && !(source instanceof JComboBox)) { id = ComponentHandler.getIdentifier(source.getParent()); } Action a = new Action(); if (source instanceof JTabbedPane) { JTabbedPane jtpn = (JTabbedPane)source; a = m_recordHelper.compSysToAction(id, "CompSystem.SelectTab"); //$NON-NLS-1$ m_recordActions.selectTab(jtpn, id, a); } else if (source instanceof JTable) { JTable jtbl = (JTable)source; int clickcount = me.getClickCount(); a = m_recordHelper.compSysToAction(id, "CompSystem.SelectCellNew"); //$NON-NLS-1$ m_recordActions.selectTableCell(jtbl, id, clickcount, a, me.getButton()); } else if (source instanceof JMenuItem && !(source instanceof JMenu)) { JMenuItem jmi = (JMenuItem)source; m_recordActions.selectMenuItem(jmi); } else if (source != null && !(source instanceof JMenu) && !(source instanceof JTree) && !(source instanceof JList) && !(source instanceof JTextComponent && ((JTextComponent)source).isEditable()) && !(source.getParent() instanceof JTable) && me.getButton() != m_popupMouseBtn) { m_recordActions.clickGraphComp(id, me, source); } } } catch (NoIdentifierForComponentException nifce) { // no identifier for the component, log this as an error log.error("no identifier for '" + getCurrentComponent()); //$NON-NLS-1$ } } /** * method for handling Key-Events * @param keyEvent AWTEvent */ private void handleKeyEvent(KeyEvent keyEvent) { synchronized (getComponentLock()) { if (keyEvent.getKeyCode() != KeyEvent.VK_UNDEFINED && keyEvent.getID() == KeyEvent.KEY_PRESSED) { final int accepted = getAcceptor().accept(keyEvent); final boolean isSingleTrigger = getAcceptor().isSingleLineTrigger(keyEvent); final boolean isMultiTrigger = getAcceptor().isMultiLineTrigger(keyEvent); IComponentIdentifier id = null; Component source = getEventSource(keyEvent); id = m_recordHelper.getApplicationCompID(); int keycode = keyEvent.getKeyCode(); if (accepted != KeyAcceptor.CHECKMODE_KEY_COMB && accepted != KeyAcceptor.CHECKCOMP_KEY_COMB) { if ((!(source instanceof JTextComponent) && !(source instanceof JComboBox) && keycode != KeyEvent.VK_ALT && keycode != KeyEvent.VK_CONTROL && keycode != KeyEvent.VK_SHIFT)) { m_recordActions.keyComboApp(id, keyEvent, keycode); } if (((source instanceof JTextField || source instanceof JComboBox) && isSingleTrigger) || ((source instanceof JTextArea || source instanceof JTextPane || source instanceof JEditorPane) && isMultiTrigger)) { m_recordActions.replaceText(source); m_recordActions.keyComboApp(id, keyEvent, keycode); } } // activates/deactivates "CheckMode" (Highlighting) if (accepted == KeyAcceptor.CHECKMODE_KEY_COMB) { if (source instanceof JTextComponent || source instanceof JComboBox) { m_recordActions.replaceText(source); } changeCheckModeState(ChangeAUTModeMessage.CHECK_MODE); } } } } /** * method for handling Focus-Events * @param event AWTEvent */ protected void handleFocusEvent(AWTEvent event) { Component source = getEventSource(event); FocusEvent fe = (FocusEvent)event; if (fe.getID() == FocusEvent.FOCUS_GAINED && (source instanceof JTextComponent || source instanceof JComboBox)) { String content = null; if (source instanceof JTextComponent) { JTextComponent textComp = (JTextComponent)source; content = textComp.getText(); } if (source instanceof JComboBox) { JComboBox cbx = (JComboBox)source; content = m_recordHelper.getRenderedComboText(cbx); } m_recordActions.addTextCompContent(source, content); m_recordActions.setComponentParent(source.getParent()); if (source.getParent() instanceof JTable) { JTable tbl = (JTable)source.getParent(); m_recordActions.setTableRowColumn(tbl.getSelectedRow(), tbl.getSelectedColumn()); } } if (fe.getID() == FocusEvent.FOCUS_LOST && (source instanceof JTextComponent || source instanceof JComboBox)) { m_recordActions.replaceText(source); } } /** * method for handling Focus-Events * @param event AWTEvent */ protected void handleWindowEvent(AWTEvent event) { Component window = getEventSource(event); IComponentIdentifier id = m_recordHelper.getApplicationCompID(); Action wfw = m_recordHelper.compSysToAction(id, "CompSystem.WaitForWindow"); //$NON-NLS-1$ Action wfwtc = m_recordHelper.compSysToAction(id, "CompSystem.WaitForWindowToClose"); //$NON-NLS-1$ if (window instanceof JFrame || window instanceof JDialog) { if ((event.getID() == WindowEvent.WINDOW_OPENED && getLastEvent().getID() != ComponentEvent.COMPONENT_SHOWN) || event.getID() == ComponentEvent.COMPONENT_SHOWN) { m_recordActions.waitForWindow(window, id, wfw); } if ((event.getID() == WindowEvent.WINDOW_CLOSED && getLastEvent().getID() != ComponentEvent .COMPONENT_HIDDEN) || event.getID() == ComponentEvent.COMPONENT_HIDDEN) { m_recordActions.waitForWindow(window, id, wfwtc); } } } /** * special handling for the JList-object in a JComboBox * @param source the source to check * @return true, if a parent of the given source is a ComboPopup */ private boolean isComboPopup(Component source) { if (source instanceof ComboPopup) { return true; } else if (source instanceof JList) { Component parent = source.getParent(); while (parent != null) { if (parent instanceof ComboPopup) { return true; } parent = parent.getParent(); } } return false; } /** * @return Returns the selectedComponent. */ protected Component getSelectedComponent() { return m_selectedComponent; } /** * @param selectedComponent The clicked/pressed Component to set. */ protected void setSelectedComponent(Component selectedComponent) { m_selectedComponent = selectedComponent; } /** * @return Returns the selectedComponentParent. */ protected Component getSelectedComponentParent() { return m_selectedComponentParent; } /** * @param selectedComponentParent The clicked/pressed ComponentParent to set. */ protected void setSelectedComponentParent( Component selectedComponentParent) { m_selectedComponentParent = selectedComponentParent; } /** * {@inheritDoc} */ public void update() { // do nothing } /** * {@inheritDoc} */ public boolean highlightComponent(IComponentIdentifier comp) { // do nothing return true; } }