Ignore:
Timestamp:
08/27/12 11:45:09 (12 years ago)
Author:
pharms
Message:
  • adapted implementation to now generate a full GUI model as well as concrete GUI interaction events
Location:
trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel
Files:
1 added
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/quest-plugin-mfc/src/main/java/de/ugoe/cs/quest/plugin/mfc/guimodel/WindowTree.java

    r578 r619  
    1 package de.ugoe.cs.quest.plugin.mfc.eventcore; 
    2  
     1 
     2package de.ugoe.cs.quest.plugin.mfc.guimodel; 
     3 
     4import java.util.ArrayList; 
    35import java.util.HashMap; 
     6import java.util.HashSet; 
    47import java.util.List; 
    58import java.util.Map; 
    6 import java.util.SortedSet; 
    7 import java.util.TreeSet; 
     9import java.util.Set; 
     10 
     11import de.ugoe.cs.quest.eventcore.guimodel.GUIElementFactory; 
     12import de.ugoe.cs.quest.eventcore.guimodel.GUIModel; 
     13import de.ugoe.cs.quest.eventcore.guimodel.GUIModelException; 
     14import de.ugoe.cs.quest.eventcore.guimodel.IGUIElementFactory; 
     15 
    816 
    917/** 
     
    1220 * </p> 
    1321 * <p> 
    14  * The window tree represents the hierarchical structure of the windows 
    15  * "as it is" currently during a session. It may change during the session due 
    16  * to creation and destruction of windows. 
    17  * </p> 
    18  * <p> 
    19  * The class is implemented as a singleton. The rational behind implementing 
    20  * this class as a singleton is to ease the access of all class that may request 
    21  * information about the windows during the parsing of a session. As the tree 
    22  * may change during the session, it does not make sense to preserve it after a 
    23  * session. Thus, it can just be deleted. Therefore, as long as only one session 
    24  * is parsed at a time, a single instance is sufficient. 
     22 * The window tree represents the hierarchical structure of the windows "as it is" currently during 
     23 * a session. It may change during the session due to creation and destruction of windows. 
    2524 * </p> 
    2625 *  
     
    3029public class WindowTree { 
    3130 
    32         /** 
    33          * <p> 
    34          * Handle to the window instance. 
    35          * </p> 
    36          */ 
    37         private static WindowTree theInstance = null; 
    38  
    39         /** 
    40          * <p> 
    41          * Maintains a set of all the target strings of all widgets that were at 
    42          * some point part of the window tree. 
    43          * </p> 
    44          */ 
    45         private SortedSet<String> targets; 
    46  
    47         /** 
    48          * <p> 
    49          * Obtain a handle to the window instance. 
    50          * </p> 
    51          *  
    52          * @return instance of the window tree 
    53          */ 
    54         public static WindowTree getInstance() { 
    55                 if (theInstance == null) { 
    56                         theInstance = new WindowTree(); 
    57                 } 
    58                 return theInstance; 
    59         } 
    60  
    61         /** 
    62          * <p> 
    63          * Resets the tree. Should be used between sessions. 
    64          * </p> 
    65          */ 
    66         public static void resetTree() { 
    67                 theInstance = null; 
    68         } 
    69  
    70         /** 
    71          * <p> 
    72          * Map of all windows that are part of the tree for efficient searching. The 
    73          * keys of the map are the hwnd's of the windows. 
    74          * </p> 
    75          */ 
    76         private Map<Integer, WindowTreeNode> nodes; 
    77  
    78         /** 
    79          * <p> 
    80          * Creates a new WindowTree. 
    81          * </p> 
    82          * <p> 
    83          * Private, as the class is a singleton. 
    84          * </p> 
    85          */ 
    86         private WindowTree() { 
    87                 nodes = new HashMap<Integer, WindowTreeNode>(); 
    88                 targets = new TreeSet<String>(); 
    89         } 
    90  
    91         /** 
    92          * <p> 
    93          * Adds a new window to the tree. 
    94          * </p> 
    95          *  
    96          * @param parentHwnd 
    97          *            hwnd of the parent window 
    98          * @param childHwnd 
    99          *            hwnd of the window to be created 
    100          * @param childWindowName 
    101          *            resource id of the window to be created 
    102          * @param resourceId 
    103          *            resource id of the window to be created 
    104          * @param className 
    105          *            class name of the window to be created 
    106          */ 
    107         public void add(int parentHwnd, int childHwnd, String childWindowName, 
    108                         int resourceId, String className, boolean isModal) { 
    109                 WindowTreeNode parent = nodes.get(parentHwnd); 
    110                 WindowTreeNode child = nodes.get(childHwnd); 
    111                 if (child == null) { 
    112                         if (parent != null) { 
    113                                 child = parent.addChild(childHwnd, childWindowName, resourceId, 
    114                                                 className, isModal); 
    115                         } else { 
    116                                 child = new WindowTreeNode(childHwnd, null, childWindowName, 
    117                                                 resourceId, className, isModal); 
    118                         } 
    119                         nodes.put(childHwnd, child); 
    120                         targets.add(child.xmlRepresentation()); 
    121                 } 
    122         } 
    123  
    124         /** 
    125          * <p> 
    126          * Removes a window (defined by its hwnd) from the tree. All children of the 
    127          * window will be removed recursively. 
    128          * </p> 
    129          *  
    130          * @param hwnd 
    131          *            hwnd of the window to be removed 
    132          * @return number of windows that were removed 
    133          */ 
    134         public int remove(int hwnd) { 
    135                 int removedCounter = 0; 
    136                 WindowTreeNode node = nodes.get(hwnd); 
    137                 if (node != null) { 
    138                         List<WindowTreeNode> nodesToBeRemoved = node.remove(); 
    139                         for (int i = 0; i < nodesToBeRemoved.size(); i++) { 
    140                                 WindowTreeNode nodeToBeRemoved = nodesToBeRemoved.get(i); 
    141                                 nodesToBeRemoved.addAll(nodeToBeRemoved.getChildren()); 
    142                                 nodes.remove(nodeToBeRemoved.getHwnd()); 
    143                                 removedCounter++; 
    144                         } 
    145                         nodes.remove(hwnd); 
    146                         removedCounter++; 
    147                 } 
    148                 return removedCounter; 
    149         } 
    150  
    151         /** 
    152          * <p> 
    153          * Searches the tree for a window with the specified hwnd and returns its 
    154          * {@link WindowTreeNode}. 
    155          * </p> 
    156          *  
    157          * @param hwnd 
    158          *            hwnd that is looked for 
    159          * @return {@link WindowTreeNode} of the window with the given hwnd if 
    160          *         found, null otherwise 
    161          */ 
    162         public WindowTreeNode find(int hwnd) { 
    163                 return nodes.get(hwnd); 
    164         } 
    165  
    166         /** 
    167          * <p> 
    168          * Returns the number of nodes contained in the WindowTree. 
    169          * </p> 
    170          *  
    171          * @return number of nodes 
    172          */ 
    173         public int size() { 
    174                 return nodes.size(); 
    175         } 
    176  
    177         /** 
    178          * <p> 
    179          * Returns a sorted set of all targets that existed any time in the window 
    180          * tree. 
    181          * </p> 
    182          *  
    183          * @return set of targets 
    184          */ 
    185         public SortedSet<String> getTargets() { 
    186                 return targets; 
    187         } 
     31    /** 
     32     * <p> 
     33     * Maintains a set of all the targets of all widgets that were at some point part of the 
     34     * window tree. 
     35     * </p> 
     36     */ 
     37    private Set<MFCGUIElementSpec> targets; 
     38 
     39    /** 
     40     * <p> 
     41     * Map of all GUI element specifications that are part of the tree for efficient searching. 
     42     * The keys of the map are the hwnd's of the GUI elements. 
     43     * </p> 
     44     */ 
     45    private Map<Long, MFCGUIElementSpec> guiElementSpecs; 
     46 
     47    /** 
     48     * <p> 
     49     * Map of all children of GUI elements that are part of the tree. The keys of the map are 
     50     * the hwnd's of the parent GUI elements. 
     51     * </p> 
     52     */ 
     53    private Map<Long, List<MFCGUIElementSpec>> childRelations; 
     54 
     55    /** 
     56     * <p> 
     57     * Map of all parents of GUI elements that are part of the tree. The keys of the map are 
     58     * the hwnd's of the child GUI elements. 
     59     * </p> 
     60     */ 
     61    private Map<Long, MFCGUIElementSpec> parentRelations; 
     62 
     63    /** 
     64     * <p> 
     65     * the internally created GUI model 
     66     * </p> 
     67     */ 
     68    private GUIModel guiModel = new GUIModel(); 
     69     
     70    /** 
     71     * <p> 
     72     * the GUI element factory used in the model 
     73     * </p> 
     74     */ 
     75    private IGUIElementFactory guiElementFactory = GUIElementFactory.getInstance(); 
     76 
     77    /** 
     78     * <p> 
     79     * Map of all GUI elements that are part of the tree for efficient searching. The keys of the 
     80     * map are the hwnd's of the GUI elements. 
     81     * </p> 
     82     */ 
     83    private Map<Long, MFCGUIElement> guiElements; 
     84 
     85    /** 
     86     * <p> 
     87     * Creates a new WindowTree. 
     88     * </p> 
     89     * <p> 
     90     * Private, as the class is a singleton. 
     91     * </p> 
     92     */ 
     93    public WindowTree() { 
     94        guiElementSpecs = new HashMap<Long, MFCGUIElementSpec>(); 
     95        targets = new HashSet<MFCGUIElementSpec>(); 
     96        childRelations = new HashMap<Long, List<MFCGUIElementSpec>>(); 
     97        parentRelations = new HashMap<Long, MFCGUIElementSpec>(); 
     98        guiElements = new HashMap<Long, MFCGUIElement>(); 
     99    } 
     100 
     101    /** 
     102     * <p> 
     103     * Adds a new window to the tree. 
     104     * </p> 
     105     *  
     106     * @param parentHwnd 
     107     *            hwnd of the parent window 
     108     * @param childHwnd 
     109     *            hwnd of the window to be created 
     110     * @param childWindowName 
     111     *            resource id of the window to be created 
     112     * @param resourceId 
     113     *            resource id of the window to be created 
     114     * @param className 
     115     *            class name of the window to be created 
     116     */ 
     117    public void add(long    parentHwnd, 
     118                    long    childHwnd, 
     119                    String  childWindowName, 
     120                    int     resourceId, 
     121                    String  className, 
     122                    boolean isModal) 
     123    { 
     124        MFCGUIElementSpec parent = guiElementSpecs.get(parentHwnd); 
     125        MFCGUIElementSpec child = guiElementSpecs.get(childHwnd); 
     126        if (child == null) { 
     127            child = 
     128                new MFCGUIElementSpec(childHwnd, childWindowName, resourceId, className, isModal); 
     129            if (parent != null) { 
     130                List<MFCGUIElementSpec> otherChildren = childRelations.get(parentHwnd); 
     131                 
     132                if (otherChildren == null) { 
     133                    otherChildren = new ArrayList<MFCGUIElementSpec>(); 
     134                    childRelations.put(parentHwnd, otherChildren); 
     135                } 
     136                 
     137                otherChildren.add(child); 
     138                 
     139                parentRelations.put(childHwnd, parent); 
     140            } 
     141            guiElementSpecs.put(childHwnd, child); 
     142            targets.add(child); 
     143        } 
     144    } 
     145 
     146    /** 
     147     * <p> 
     148     * Searches the tree for a window with the specified hwnd and returns its {@link MFCGUIElementSpec} 
     149     * . 
     150     * </p> 
     151     *  
     152     * @param hwnd 
     153     *            hwnd that is looked for 
     154     * @return {@link MFCGUIElementSpec} of the window with the given hwnd if found, null otherwise 
     155     */ 
     156    public MFCGUIElement find(long hwnd) { 
     157        MFCGUIElement guiElement = guiElements.get(hwnd); 
     158        if (guiElement == null) { 
     159            List<MFCGUIElementSpec> guiElementPath = new ArrayList<MFCGUIElementSpec>(); 
     160             
     161            MFCGUIElementSpec child = guiElementSpecs.get(hwnd); 
     162             
     163            if (child == null) { 
     164                throw new RuntimeException("no GUI element found with id " + hwnd); 
     165            } 
     166             
     167            while (child != null) { 
     168                guiElementPath.add(0, child); 
     169                child = parentRelations.get(child.getHwnd()); 
     170            } 
     171             
     172            try { 
     173                guiElement = (MFCGUIElement) 
     174                    guiModel.integratePath(guiElementPath, guiElementFactory); 
     175            } 
     176            catch (GUIModelException e) { 
     177                throw new RuntimeException("could not instantiate GUI element with id " + hwnd, e); 
     178            } 
     179            guiElements.put(hwnd, guiElement); 
     180        } 
     181        return guiElement; 
     182    } 
     183 
     184    /** 
     185     * <p> 
     186     * TODO: comment 
     187     * </p> 
     188     * 
     189     * @param hwnd 
     190     * @param windowName 
     191     */ 
     192    public void setName(long hwnd, String windowName) { 
     193        MFCGUIElementSpec child = guiElementSpecs.get(hwnd); 
     194        if (child != null) { 
     195            child.setName(windowName); 
     196 
     197            MFCGUIElement guiElement = guiElements.remove(hwnd); 
     198            if (guiElement == null) { 
     199                // we need to update the GUI model as well 
     200                find(hwnd); 
     201            } 
     202        } 
     203    } 
     204     
     205    /** 
     206     * <p> 
     207     * Removes a window (defined by its hwnd) from the tree. All children of the window will be 
     208     * removed recursively. 
     209     * </p> 
     210     *  
     211     * @param hwnd 
     212     *            hwnd of the window to be removed 
     213     * @return number of windows that were removed 
     214     */ 
     215    public int remove(long hwnd) { 
     216        MFCGUIElementSpec node = guiElementSpecs.remove(hwnd); 
     217        int removedCounter = 1; 
     218         
     219        if (node != null) { 
     220            List<MFCGUIElementSpec> nodesToBeRemoved = childRelations.remove(hwnd); 
     221             
     222            // remove all children and sub-children, if any 
     223            if (nodesToBeRemoved != null) { 
     224                for (int i = 0; i < nodesToBeRemoved.size(); i++) { 
     225                    MFCGUIElementSpec nodeToBeRemoved = nodesToBeRemoved.get(i); 
     226                    List<MFCGUIElementSpec> children = 
     227                        childRelations.remove(nodeToBeRemoved.getHwnd()); 
     228                     
     229                    if (children != null) { 
     230                        nodesToBeRemoved.addAll(children); 
     231                    } 
     232                     
     233                    guiElementSpecs.remove(nodeToBeRemoved.getHwnd()); 
     234                    parentRelations.remove(nodeToBeRemoved.getHwnd()); 
     235                    removedCounter++; 
     236                } 
     237            } 
     238 
     239            // the node may be a child node of a parent. So search for it and remove it 
     240            MFCGUIElementSpec parent = parentRelations.remove(hwnd); 
     241            if (parent != null) { 
     242                List<MFCGUIElementSpec> children = childRelations.get(parent.getHwnd()); 
     243 
     244                if (children != null) { 
     245                    for (int i = 0; i < children.size(); i++) { 
     246                        if (children.get(i).getHwnd() == hwnd) { 
     247                            children.remove(i); 
     248                            break; 
     249                        } 
     250                    } 
     251                     
     252                    if (children.size() <= 0) { 
     253                        childRelations.remove(parent.getHwnd()); 
     254                    } 
     255                } 
     256            } 
     257        } 
     258        return removedCounter; 
     259    } 
     260 
     261    /** 
     262     * @return the guiModel 
     263     */ 
     264    public GUIModel getGUIModel() { 
     265        return guiModel; 
     266    } 
     267 
     268    /** 
     269     * <p> 
     270     * Returns the number of nodes contained in the WindowTree. 
     271     * </p> 
     272     *  
     273     * @return number of nodes 
     274     */ 
     275    public int size() { 
     276        return guiElementSpecs.size(); 
     277    } 
     278 
     279    /** 
     280     * <p> 
     281     * Returns a sorted set of all targets that existed any time in the window tree. 
     282     * </p> 
     283     *  
     284     * @return set of targets 
     285     */ 
     286    public Set<MFCGUIElementSpec> getTargets() { 
     287        return targets; 
     288    } 
     289 
    188290} 
Note: See TracChangeset for help on using the changeset viewer.