Changeset 611
- Timestamp:
- 08/27/12 11:33:58 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/quest-core-events/src/main/java/de/ugoe/cs/quest/eventcore/guimodel/GUIModel.java
r603 r611 42 42 throws GUIModelException 43 43 { 44 if ((guiElementPath == null) || (guiElementPath.size() <= 0)) { 45 throw new IllegalArgumentException 46 ("GUI element path must contain at least one element"); 47 } 48 44 49 List<IGUIElementSpec> remainingPath = new LinkedList<IGUIElementSpec>(); 45 50 … … 103 108 public List<IGUIElement> getRootElements() { 104 109 List<IGUIElement> roots = new ArrayList<IGUIElement>(); 105 for (TreeNode rootChild : root.children) { 106 roots.add(rootChild.guiElement); 107 } 110 111 if (root.children != null) { 112 for (TreeNode rootChild : root.children) { 113 roots.add(rootChild.guiElement); 114 } 115 } 116 108 117 return roots; 109 118 } … … 126 135 { 127 136 IGUIElementSpec specToIntegrateElementFor = remainingPath.remove(0); 128 129 List<TreeNode> matchingChildren = new ArrayList<TreeNode>(); 137 138 List<TreeNode> similarNodes = 139 determineSimilarChildNodes(parentNode, specToIntegrateElementFor); 140 141 if (similarNodes.size() > 1) { 142 // this may happen, if the GUI elements changed over time (e.g. their name is usually 143 // set later in the program execution) and if they now match because of the changes. 144 // So perform a merge of all similar children of the current parent node to reduce the 145 // model and then try the determination of matching children again. 146 mergeSimilarChildren(parentNode); 147 similarNodes = determineSimilarChildNodes(parentNode, specToIntegrateElementFor); 148 149 if (similarNodes.size() > 1) { 150 // this can happen, because the similarity check is not transitive. The new GUI 151 // element may be similar to two or more existing ones, but the existing ones 152 // may not be similar to each other. As an example, the new GUI element may 153 // not yet provide sufficient information (such as all names it will have during 154 // the execution of the program). Therefore the similarity check with GUI elements 155 // that already contain more information may return true. But the similarity check 156 // of two GUI elements that already carry a lot of information may return false, 157 // although both are similar to the new GUI element. Therefore, we try a selection 158 // based on the children of the existing and new GUI elements. The one for which 159 // the existing children match best is selected to be the right one. 160 similarNodes = 161 considerSubChildren(similarNodes, specToIntegrateElementFor, remainingPath); 162 163 if (similarNodes.size() > 1) { 164 System.out.println("TODO: implement handling to many similar children: " + 165 specToIntegrateElementFor); 166 for (TreeNode similarNode : similarNodes) { 167 System.out.println(" " + similarNode.guiElement); 168 } 169 System.out.println(); 170 } 171 } 172 } 173 else if (similarNodes.size() == 1) { 174 similarNodes.get(0).guiElement.updateSpecification(specToIntegrateElementFor); 175 } 176 else if (similarNodes.size() == 0) { 177 // if we get here, the corresponding path does not exist yet. So create it 178 IGUIElement newElement = guiElementFactory.instantiateGUIElement 179 (specToIntegrateElementFor, parentNode.guiElement); 180 181 similarNodes.add(parentNode.addChild(newElement)); 182 } 183 184 if (remainingPath.size() > 0) { 185 return integratePath(similarNodes.get(0), remainingPath, guiElementFactory); 186 } 187 else { 188 return similarNodes.get(0).guiElement; 189 } 190 } 191 192 /** 193 * <p> 194 * TODO: comment 195 * </p> 196 * 197 * @param parentNode 198 * @param specToIntegrateElementFor 199 * @return 200 */ 201 private List<TreeNode> determineSimilarChildNodes(TreeNode parentNode, 202 IGUIElementSpec specToMatch) 203 { 204 List<TreeNode> similarChildren = new ArrayList<TreeNode>(); 130 205 131 206 if (parentNode.children != null) { 132 207 for (TreeNode child : parentNode.children) { 133 if (specToIntegrateElementFor.getSimilarity(child.guiElement.getSpecification())) { 134 matchingChildren.add(child); 135 } 136 } 137 } 138 139 // if we get here, the corresponding path does not exist yet. So create it 140 if (matchingChildren.size() == 0) { 141 IGUIElement newElement = guiElementFactory.instantiateGUIElement 142 (specToIntegrateElementFor, parentNode.guiElement); 143 144 matchingChildren.add(parentNode.addChild(newElement)); 145 } 146 else if (matchingChildren.size() > 1) { 147 throw new GUIModelException 148 ("several children of gui element " + parentNode.guiElement + 149 " match the specification " + specToIntegrateElementFor + " at the same level. " + 150 "Can not decide which is the right one."); 151 } 152 153 if (remainingPath.size() > 0) { 154 matchingChildren.get(0).guiElement.updateSpecification(specToIntegrateElementFor); 155 return integratePath(matchingChildren.get(0), remainingPath, guiElementFactory); 208 if (specToMatch.getSimilarity(child.guiElement.getSpecification())) { 209 similarChildren.add(child); 210 } 211 } 212 } 213 214 return similarChildren; 215 } 216 217 /** 218 * <p> 219 * TODO: comment 220 * </p> 221 * 222 * @param similarChildren 223 * @param remove 224 * @return 225 */ 226 private List<TreeNode> considerSubChildren(List<TreeNode> similarNodes, 227 IGUIElementSpec specToMatch, 228 List<? extends IGUIElementSpec> remainingPath) 229 { 230 List<TreeNode> reducedList = new ArrayList<TreeNode>(); 231 232 // check, if there are any children to consider and remove any similar node, that has 233 // further children 234 if (remainingPath.size() <= 0) { 235 for (TreeNode similarNode : similarNodes) { 236 if ((similarNode.children == null) || (similarNode.children.size() == 0)) { 237 reducedList.add(similarNode); 238 } 239 } 156 240 } 157 241 else { 158 return matchingChildren.get(0).guiElement; 159 } 242 // if there are further children to consider, then check if there is already a child 243 // node that has an appropriate child 244 IGUIElementSpec subChildSpec = remainingPath.get(0); 245 for (TreeNode similarNode : similarNodes) { 246 if (similarNode.children != null) { 247 for (TreeNode subchild : similarNode.children) { 248 if (subchild.guiElement.getSpecification().getSimilarity(subChildSpec)) { 249 reducedList.add(similarNode); 250 break; 251 } 252 } 253 } 254 } 255 } 256 257 return reducedList; 258 } 259 260 /** 261 * <p> 262 * TODO: comment 263 * </p> 264 * 265 * @param parentNode 266 */ 267 private void mergeSimilarChildren(TreeNode parentNode) { 268 boolean performedMerge; 269 270 do { 271 performedMerge = false; 272 if (parentNode.children != null) { 273 for (int i = 0; (!performedMerge) && (i < parentNode.children.size()); i++) { 274 for (int j = i + 1; j < parentNode.children.size(); j++) { 275 IGUIElement elem1 = parentNode.children.get(i).guiElement; 276 IGUIElement elem2 = parentNode.children.get(j).guiElement; 277 if (elem1.getSpecification().getSimilarity(elem2.getSpecification())) { 278 TreeNode replacement = mergeTreeNodes(parentNode.children.get(i), 279 parentNode.children.get(j)); 280 281 parentNode.children.set(i, replacement); 282 parentNode.children.remove(j); 283 performedMerge = true; 284 break; 285 } 286 } 287 } 288 } 289 } 290 while (performedMerge); 291 } 292 293 /** 294 * <p> 295 * TODO: comment 296 * </p> 297 * 298 * @param treeNode 299 * @param treeNode2 300 * @return 301 */ 302 private TreeNode mergeTreeNodes(TreeNode treeNode1, TreeNode treeNode2) { 303 TreeNode replacement = new TreeNode(); 304 305 replacement.guiElement = treeNode1.guiElement; 306 307 // the following two lines are needed to preserve the references to the existing GUI 308 // elements. If two elements are the same, one should be deleted to make the elements 309 // singletons again. However, there may exist references to both objects. To preserve 310 // these, we simply register the equal GUI elements with each other so that an equals 311 // check can return true. 312 replacement.guiElement.addEqualGUIElement(treeNode2.guiElement); 313 treeNode2.guiElement.addEqualGUIElement(replacement.guiElement); 314 315 if (treeNode1.children != null) { 316 for (TreeNode child : treeNode1.children) { 317 replacement.addChild(child.guiElement); 318 } 319 } 320 321 if (treeNode2.children != null) { 322 for (TreeNode child : treeNode2.children) { 323 replacement.addChild(child.guiElement); 324 } 325 } 326 327 mergeSimilarChildren(replacement); 328 329 replacement.guiElement.updateSpecification(treeNode2.guiElement.getSpecification()); 330 331 return replacement; 160 332 } 161 333
Note: See TracChangeset
for help on using the changeset viewer.