// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.plugin.jfc.guimodel; import de.ugoe.cs.autoquest.eventcore.guimodel.AbstractDefaultGUIElement; import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElementSpec; import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; /** *

* Base class for all JFC GUI elements. *

* * @version 1.0 * @author Patrick Harms */ public class JFCGUIElement extends AbstractDefaultGUIElement { /** *

* Id for object serialization. *

*/ private static final long serialVersionUID = 1L; /** *

* the default distance value for different applications *

*/ protected static final double DISTANCE_DISTINCT_APPLICATION = 1.0; /** *

* the default distance value for same application but different views, i.e., dialogs, frames, * or tabbed panes *

*/ protected static final double DISTANCE_SAME_APPLICATION = 0.75; /** *

* the default distance value for same view but different panels *

*/ protected static final double DISTANCE_SAME_VIEW = 0.5; /** *

* the default distance value for same parent panel but different GUI elements *

*/ protected static final double DISTANCE_SAME_PANEL = 0.2; /** *

* the default distance value for identical GUI elements *

*/ protected static final double DISTANCE_NONE = 0.0; /** *

* Specification of the GUI Element *

*/ private JFCGUIElementSpec specification; /** *

* Constructor. Creates a new JFCGUIElement. *

* * @param specification * specification of created GUI element * @param parent * parent of the created GUI element; null means that the element is a top-level * window */ public JFCGUIElement(JFCGUIElementSpec specification, JFCGUIElement parent) { super(specification, parent); this.specification = specification; } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.eventcore.IEventTarget#getPlatform() */ @Override public String getPlatform() { return "JFC"; } /** *

* Returns the type of the GUI element, i.e., the name of its Java class. *

* * @return the Java class name */ public String getJavaType() { return specification.getType(); } /** *

* Returns the name of the GUI element. *

* * @return the name */ public String getName() { return specification.getName(); } /** *

* Returns the icon of the GUI element. *

* * @return the icon */ String getIcon() { return specification.getIcon(); } /** *

* Returns the index of the GUI element. *

* * @return the index */ int getIndex() { return specification.getIndex(); } /** *

* Returns the object hash of the GUI element. *

* * @return the object hash */ int getElementHash() { return specification.getElementHash(); } /* * (non-Javadoc) * * @see * de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#updateSpecification(de.ugoe.cs.autoquest * .eventcore .guimodel.IGUIElementSpec) */ @Override public void updateSpecification(IGUIElementSpec updateSpecification) { if (updateSpecification instanceof JFCGUIElementSpec) { specification.update(((JFCGUIElementSpec) updateSpecification)); } } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String getStringIdentifier() { String str = this.toString(); if (getParent() != null) { return str + "<-" + getParent().getStringIdentifier(); } return str; } public String getJacaretoHierarchy() { String str; // get the Java classname, ignore the package hierarchy if present String[] parts = getSpecification().getType().split("\\."); // find the correct Jacareto index // jacareto indices start at 1 int jacIndex = ((JFCGUIElementSpec) getSpecification()).getAltIndex() + 1; str = parts[parts.length - 1] + "_(" + jacIndex + ")"; if (getParent() != null) { return ((JFCGUIElement) getParent()).getJacaretoHierarchy() + "." + str; } return str; } public String getJacaretoRoot() { return getJacaretoHierarchy().split("\\.")[0]; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { String str = getElementDescriptor() + "(" + getName() + "," + getElementHash() + "," + getIcon() + "," + getIndex() + ")"; return str; } /* (non-Javadoc) * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getView() */ @Override public IGUIView getView() { JFCGUIElement element = this; while ((element != null) && (!(element instanceof JFCFrame)) && (!(element instanceof JFCDialog))) { if (!(element.getParent() instanceof JFCTabbedPane)) { element = (JFCGUIElement) element.getParent(); } else { // break, as all children of a tabbed pane are always views break; } } return new JFCView(element); } /* * (non-Javadoc) * * @see de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement#getDistanceTo(IGUIElement) */ @Override public double getDistanceTo(IGUIElement otherElement) { if (otherElement instanceof JFCGUIElement) { if (equals(otherElement)) { return DISTANCE_NONE; } if (!areInSameView(this, otherElement)) { IGUIElement root1 = this; while (root1.getParent() != null) { root1 = root1.getParent(); } IGUIElement root2 = otherElement; while (root2.getParent() != null) { root2 = root2.getParent(); } if (!root1.equals(root2)) { return DISTANCE_DISTINCT_APPLICATION; } else { return DISTANCE_SAME_APPLICATION; } } else { // check if they have the same parent panel. If so, they are very close. // If not, they may be structured completely differently IGUIElement parentPanel1 = this; while (parentPanel1 != null) { if ((parentPanel1 instanceof JFCPanel) || (parentPanel1 instanceof JFCFrame) || (parentPanel1 instanceof JFCDialog) || (parentPanel1 instanceof JFCCanvas) || (parentPanel1 instanceof JFCMenu) || (parentPanel1 instanceof JFCScrollPane) || (parentPanel1 instanceof JFCSplitPane) || (parentPanel1 instanceof JFCTabbedPane)) { break; } else { parentPanel1 = parentPanel1.getParent(); } } IGUIElement parentPanel2 = otherElement; while (parentPanel2 != null) { if ((parentPanel2 instanceof JFCPanel) || (parentPanel2 instanceof JFCFrame) || (parentPanel2 instanceof JFCDialog) || (parentPanel2 instanceof JFCCanvas) || (parentPanel2 instanceof JFCMenu) || (parentPanel2 instanceof JFCScrollPane) || (parentPanel2 instanceof JFCSplitPane) || (parentPanel2 instanceof JFCTabbedPane)) { break; } else { parentPanel2 = parentPanel2.getParent(); } } // a check for the identity of the objects is sufficient. That they resist on the // same document was checked beforehand. So even a condense of the GUI model should // not cause an invalid result here. if ((parentPanel1 == parentPanel2) || ((parentPanel1 != null) && (parentPanel1.equals(parentPanel2)))) { return DISTANCE_SAME_PANEL; } else { return DISTANCE_SAME_VIEW; } } } return DISTANCE_DISTINCT_APPLICATION; } /** *

* A short string describing the GUI element, e.g., Button, Canvas, or ScrollBar. *

* * @return short element descriptor */ protected String getElementDescriptor() { return "Default"; } /** *

* convenience method to check if two GUI elements are in the same view. In contrast to other * technologies, JFC GUI views may have other views as children. Hence, it is not sufficient to * check, if the direct parent views are identical. *

*/ private boolean areInSameView(IGUIElement guiElement1, IGUIElement guiElement2) { IGUIView view1 = guiElement1.getView(); IGUIElement other = guiElement2; while (other != null) { if (view1.equals(other.getView())) { return true; } other = other.getParent(); } // the parent views of the other gui element are checked. But not the ones of this. Hence, // check also them. if ((view1 instanceof JFCView) && (((JFCView) view1).getParent() != null)) { return areInSameView(((JFCView) view1).getParent(), guiElement2); } else { return false; } } }