Index: /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/commands/CMDgenerateJacaretoReplay.java
===================================================================
--- /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/commands/CMDgenerateJacaretoReplay.java	(revision 1824)
+++ /trunk/autoquest-plugin-jfc/src/main/java/de/ugoe/cs/autoquest/plugin/jfc/commands/CMDgenerateJacaretoReplay.java	(revision 1825)
@@ -20,4 +20,7 @@
 import java.io.IOException;
 import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -26,4 +29,5 @@
 import java.util.Iterator;
 import java.util.List;
+import java.util.Stack;
 import java.util.UUID;
 import java.util.logging.Level;
@@ -35,6 +39,10 @@
 import de.ugoe.cs.autoquest.eventcore.IEventTarget;
 import de.ugoe.cs.autoquest.eventcore.gui.*;
+import de.ugoe.cs.autoquest.eventcore.guimodel.GUIModel;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
 import de.ugoe.cs.autoquest.keyboardmaps.VirtualKey;
 import de.ugoe.cs.autoquest.plugin.jfc.guimodel.JFCGUIElement;
+import de.ugoe.cs.autoquest.plugin.jfc.guimodel.JFCMenu;
+import de.ugoe.cs.autoquest.plugin.jfc.guimodel.JFCMenuButton;
 import de.ugoe.cs.util.console.Console;
 import de.ugoe.cs.util.console.GlobalDataContainer;
@@ -113,4 +121,6 @@
     private StructureNode lastItemActionEvent;
     private IEventTarget lastMouseDownTarget;
+    private HashMap<String, JFCGUIElement> menuElements;
+    private List<String> menuList;
 
     /*
@@ -121,5 +131,5 @@
     @Override
     public String help() {
-        return "generateJacaretoReplay <filename> <sequences> <class> <basepath> <classpathext> {<initclass>}";
+        return "generateJacaretoReplay <filename> <sequences> <class> <basepath> <classpathext> {<menufile>}";
     }
 
@@ -137,5 +147,4 @@
         String basepath;
         String classpathext;
-        String initclass = "";
         try {
             filename = (String) parameters.get(0);
@@ -150,5 +159,13 @@
 
         if (parameters.size() > 5) {
-            initclass = (String) parameters.get(5);
+            try {
+                menuList =
+                    Files.readAllLines(Paths.get((String) parameters.get(5)),
+                                       Charset.defaultCharset());
+            }
+            catch (IOException e) {
+                Console.printerrln("Unable to open menu file");
+                Console.logException(e);
+            }
         }
 
@@ -165,4 +182,6 @@
 
         sequences = (Collection<List<Event>>) dataObject;
+
+        menuElements = new HashMap<>();
 
         // map which maps VirtualKeys back to awt key modifier codes
@@ -176,5 +195,5 @@
         StructureNode.nextRef = 0;
 
-        writeJacaretoXML(sequences, filename, classpath, initclass, basepath, classpathext);
+        writeJacaretoXML(sequences, filename, classpath, basepath, classpathext);
     }
 
@@ -186,5 +205,4 @@
     private void writeJacaretoHead(BufferedWriter writer,
                                    String classname,
-                                   String initclass,
                                    String basepath,
                                    String classpathext) throws IOException
@@ -218,5 +236,5 @@
             + "name=\"Autoquest Replay\" "
             + "class=\"" + classname + "\" "
-            + "initclass=\"" + initclass + "\" " 
+            + "initclass=\"\" " 
             + "basepath=\"" + basepath + "\" "
             + "classpathext=\"" + classpathext + "\" "
@@ -250,10 +268,12 @@
                     lastMouseClickEvent = new StructureNode("MouseClick");
                     lastMouseDownTarget = event.getTarget();
-                    writeMouseClickEvent(writer, event, EVENT_DURATION, 501);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         EVENT_DURATION, 501);
                 }
                 else if (event.getType() instanceof MouseButtonUp) {
                     lastKeySequenceEvent = null;
 
-                    writeMouseClickEvent(writer, event, EVENT_DURATION, 502);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         EVENT_DURATION, 502);
                 }
                 else if (event.getType() instanceof MouseDoubleClick) {
@@ -262,16 +282,42 @@
                     // first click
                     lastMouseClickEvent = multiClick.add("MouseClick");
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 501);
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 502);
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 500);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 501);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 502);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 500);
                     // second click
                     lastMouseClickEvent = multiClick.add("MouseClick");
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 501);
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 502);
-                    writeMouseClickEvent(writer, event, DOUBLE_CLICK_DURATION, 500);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 501);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 502);
+                    writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                         DOUBLE_CLICK_DURATION, 500);
 
                     lastMouseClickEvent = null;
                 }
                 else if (event.getType() instanceof MouseClick) {
+                    // if a menu file was provided, use the improved event
+                    // generation
+                    if (menuList != null) {
+                        if (event.getTarget() instanceof JFCMenuButton) {
+                            if (menuElements.isEmpty()) {
+                                // parse the menu structure
+                                GUIModel model = ((IGUIElement) event.getTarget()).getGUIModel();
+                                getMenuElements(model.getRootElements(), model);
+                            }
+
+                            Stack<JFCGUIElement> hierarchy =
+                                findMenuItemHierarchy((JFCGUIElement) event.getTarget());
+
+                            while (!hierarchy.empty()) {
+                                generateFullClick(writer, event, hierarchy.pop());
+                            }
+                            continue;
+                        }
+                    }
+
                     lastKeySequenceEvent = null;
 
@@ -282,5 +328,6 @@
                             // was triggered on this target
 
-                            writeMouseClickEvent(writer, event, EVENT_DURATION, 500);
+                            writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                                 EVENT_DURATION, 500);
                             writeItemActionEvent(writer, event);
 
@@ -307,9 +354,10 @@
 
                             // finish the last click on the old target
-                            writeMouseClickEvent(writer, event, EVENT_DURATION, 500);
+                            writeMouseClickEvent(writer, event, (JFCGUIElement) event.getTarget(),
+                                                 EVENT_DURATION, 500);
                             structure.children.add(lastMouseClickEvent);
 
                             // and generate a new one
-                            generateFullClick(writer, event);
+                            generateFullClick(writer, event, (JFCGUIElement) event.getTarget());
                         }
                     }
@@ -319,5 +367,5 @@
                         // mouseUps anymore
                         // -> just generate another full click
-                        generateFullClick(writer, event);
+                        generateFullClick(writer, event, (JFCGUIElement) event.getTarget());
                     }
                 }
@@ -345,4 +393,42 @@
     }
 
+    private void getMenuElements(List<IGUIElement> elements, GUIModel model) {
+        for (IGUIElement child : elements) {
+            if (child instanceof JFCMenuButton || child instanceof JFCMenu) {
+                menuElements.put(((JFCGUIElement) child).getName().replaceAll("^\"|\"$", ""),
+                                 (JFCGUIElement) child);
+            }
+            getMenuElements(model.getChildren(child), model);
+        }
+    }
+
+    private Stack<JFCGUIElement> findMenuItemHierarchy(JFCGUIElement item) {
+        Stack<JFCGUIElement> elements = new Stack<>();
+
+        // find line that contains this menu item name
+        int lineOfItem = -1;
+        for (int i = 0; i < menuList.size(); i++) {
+            String name = "\"" + menuList.get(i).trim().toLowerCase() + "\"";
+            if (name.equals(item.getName().trim().toLowerCase())) {
+                lineOfItem = i;
+            }
+        }
+
+        // now go backwards until the toplevel menu is found
+        int oldIndent = Integer.MAX_VALUE;
+        for (int j = lineOfItem; j >= 0; j--) {
+            String stripped = menuList.get(j).replaceFirst("^ *", "");
+            int indent = menuList.get(j).length() - stripped.length();
+
+            if (indent < oldIndent) {
+                // this is a parent submenu
+                elements.add(menuElements.get(stripped));
+                oldIndent = indent;
+            }
+        }
+
+        return elements;
+    }
+
     private void commitFocusEvent() {
         if (lastFocusChangeEvent != null) {
@@ -352,11 +438,13 @@
     }
 
-    private void generateFullClick(BufferedWriter writer, Event event) throws IOException {
+    private void generateFullClick(BufferedWriter writer, Event event, JFCGUIElement target)
+        throws IOException
+    {
         lastMouseClickEvent = new StructureNode("MouseClick");
         lastMouseDownTarget = event.getTarget();
 
-        writeMouseClickEvent(writer, event, EVENT_DURATION, 501);
-        writeMouseClickEvent(writer, event, EVENT_DURATION, 502);
-        writeMouseClickEvent(writer, event, EVENT_DURATION, 500);
+        writeMouseClickEvent(writer, event, target, EVENT_DURATION, 501);
+        writeMouseClickEvent(writer, event, target, EVENT_DURATION, 502);
+        writeMouseClickEvent(writer, event, target, EVENT_DURATION, 500);
         writeItemActionEvent(writer, event);
 
@@ -365,5 +453,4 @@
 
         lastMouseDownTarget = null;
-
     }
 
@@ -381,5 +468,4 @@
                                   String filename,
                                   String classpath,
-                                  String initclass,
                                   String basepath,
                                   String classpathext)
@@ -388,5 +474,5 @@
 
         try {
-            writeJacaretoHead(writer, classpath, initclass, basepath, classpathext);
+            writeJacaretoHead(writer, classpath, basepath, classpathext);
             writeJacaretoEvents(writer, sequences);
             writeJacaretoTail(writer);
@@ -519,12 +605,13 @@
     }
 
-    private void writeMouseClickEvent(BufferedWriter writer, Event event, int duration, int jacId)
-        throws IOException
+    private void writeMouseClickEvent(BufferedWriter writer,
+                                      Event event,
+                                      JFCGUIElement target,
+                                      int duration,
+                                      int jacId) throws IOException
     {
         MouseButtonInteraction info = (MouseButtonInteraction) event.getType();
-        JFCGUIElement target = (JFCGUIElement) event.getTarget();
         int clickCount = event.getType() instanceof MouseDoubleClick ? 2 : 1;
 
-        // TODO: change procTime and duration to adequate values
         //@formatter:off
         writeLine(writer,
