diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/ScreenGenerator.java b/java_tools/ts_screenshots/screen/src/com/rusefi/ScreenGenerator.java index 31109e9caf..79144c82a3 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/ScreenGenerator.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/ScreenGenerator.java @@ -1,6 +1,5 @@ package com.rusefi; -import com.opensr5.ini.DialogModel; import com.opensr5.ini.IniFileModel; import com.rusefi.xml.*; @@ -16,18 +15,20 @@ import java.util.List; import java.util.concurrent.atomic.AtomicReference; public class ScreenGenerator { - public static final String TS_DIALOG = "com.efiAnalytics.ui.dg"; - public static final String PNG = "png"; - private static final int MENU_CLICK_DELAY = 300; - private static final int TOP_MENU_CLICK_DELAY = 1000; + private static final String PNG = "png"; private static ArrayList topLevelButtons = new ArrayList<>(); + private static final int MENU_CLICK_DELAY = 50; + private static final int TOP_MENU_CLICK_DELAY = 200; + private static final int WAITING_FOR_FRAME_PERIOD = 1000; + + private static final String DESTINATION = "images" + File.separator; - static Content content = new Content(); + static ContentModel contentModel = new ContentModel(); static IniFileModel iniFileModel = new IniFileModel(); - static Map byCleanUiName = new TreeMap<>(); + static Map byCleanUiName = new TreeMap<>(); public static void main(String[] args) throws Exception { if (args.length != 1) { @@ -37,7 +38,7 @@ public class ScreenGenerator { iniFileModel.readIniFile("."); - for (Map.Entry a : iniFileModel.getAllFields().entrySet()) { + for (Map.Entry a : iniFileModel.getAllFields().entrySet()) { String cleanUiName = cleanName(a.getValue().getUiName()); byCleanUiName.put(cleanUiName, a.getValue()); } @@ -50,7 +51,7 @@ public class ScreenGenerator { new File(DESTINATION).mkdirs(); System.out.println("Launching TunerStudioIntegraion"); - Frame mainFrame = TunerStudioIntegraion.findMainFrame(); + Frame mainFrame = TunerStudioIntegration.findMainFrame(); waitForMainFrame(mainFrame); @@ -58,7 +59,7 @@ public class ScreenGenerator { handleTopLevelButtons(mainFrame, topLevelButtons); - XmlUtil.writeXml(content); + XmlUtil.writeXml(contentModel); } private static void waitForMainFrame(Frame mainFrame) throws InterruptedException { @@ -68,47 +69,50 @@ public class ScreenGenerator { AbstractButton ab = (AbstractButton) component; System.out.println("topLevelButton " + ab.getText()); - if (TunerStudioIntegraion.isTopLevelMenuButton(component)) { + if (TunerStudioIntegration.isTopLevelMenuButton(component)) { topLevelButtons.add(ab); } } }); - Thread.sleep(1000); + Thread.sleep(WAITING_FOR_FRAME_PERIOD); } } private static void handleTopLevelButtons(Frame frame, ArrayList topLevelButtons) throws Exception { for (AbstractButton topLevel : topLevelButtons) { - handleTopLevelButton(frame, topLevel, content); + handleTopLevelButton(frame, topLevel); } } - private static void handleTopLevelButton(Frame frame, AbstractButton topLevel, Content content) throws Exception { + private static void handleTopLevelButton(Frame frame, AbstractButton topLevel) throws Exception { SwingUtilities.invokeAndWait(topLevel::doClick); Thread.sleep(TOP_MENU_CLICK_DELAY); - TopLevelMenu topLevelMenu = new TopLevelMenu(topLevel.getText()); - ScreenGenerator.content.getTopLevelMenus().add(topLevelMenu); + + String imageName = "top_level_" + cleanName(topLevel.getText()) + "." + PNG; + + TopLevelMenuModel topLevelMenuModel = new TopLevelMenuModel(topLevel.getText(), imageName); + ScreenGenerator.contentModel.getTopLevelMenus().add(topLevelMenuModel); ImageIO.write( UiUtils.getScreenShot(frame), - "png", - new File(DESTINATION + cleanName(topLevel.getText()) + ".png")); + PNG, + new File(DESTINATION + imageName)); - List menuItems = TunerStudioIntegraion.findMenuItems(frame); + List menuItems = TunerStudioIntegration.findMenuItems(frame); for (JMenuItem menuItem : menuItems) { - handleMenuItem(menuItem, topLevelMenu); + handleMenuItem(menuItem, topLevelMenuModel); } } - private static void handleMenuItem(JMenuItem menuItem, TopLevelMenu topLevelMenu) throws InterruptedException, InvocationTargetException { + private static void handleMenuItem(JMenuItem menuItem, TopLevelMenuModel topLevelMenuModel) throws InterruptedException, InvocationTargetException { SwingUtilities.invokeAndWait(menuItem::doClick); Thread.sleep(MENU_CLICK_DELAY); AtomicReference ref = new AtomicReference<>(); - SwingUtilities.invokeAndWait(() -> ref.set(TunerStudioIntegraion.findDynamicDialog())); + SwingUtilities.invokeAndWait(() -> ref.set(TunerStudioIntegration.findDynamicDialog())); // let's give it time to appear on the screen Thread.sleep(MENU_CLICK_DELAY); JDialog dialog = ref.get(); @@ -119,13 +123,13 @@ public class ScreenGenerator { String dialogTitle = dialog.getTitle(); - - DialogDescription dialogDescription = new DialogDescription(dialogTitle); - topLevelMenu.getDialogs().add(dialogDescription); + String imageName = "dialog_" + cleanName(dialogTitle) + "." + PNG; + DialogModel dialogModel = new DialogModel(dialogTitle, imageName); + topLevelMenuModel.getDialogs().add(dialogModel); SwingUtilities.invokeAndWait(() -> { try { - findSlices(dialog, dialogDescription); + findSlices(dialog, dialogModel); if (dialog == null) { // this happens for example for disabled menu items @@ -141,7 +145,7 @@ public class ScreenGenerator { ImageIO.write( dialogScreenShot, PNG, - new File(DESTINATION + cleanName(dialogTitle) + ".png")); + new File(DESTINATION + imageName)); dialog.setVisible(false); dialog.dispose(); } catch (Exception e) { @@ -150,7 +154,7 @@ public class ScreenGenerator { }); } - private static void saveSlices(String dialogTitle, Map yCoordinates, BufferedImage dialogScreenShot, DialogDescription dialogDescription) { + private static void saveSlices(String dialogTitle, Map yCoordinates, BufferedImage dialogScreenShot, DialogModel dialogModel) { System.out.println("Label Y coordinates: " + yCoordinates); yCoordinates.put(0, "top"); yCoordinates.put(dialogScreenShot.getHeight(), "bottom"); @@ -176,16 +180,16 @@ public class ScreenGenerator { System.out.println("Weird"); continue; } - String fileName = cleanName(dialogTitle) + "_slice_" + fromY + "_" + sectionName + ".png"; + String fileName = cleanName(dialogTitle) + "_slice_" + fromY + "_" + sectionName + "." + PNG; - DialogModel.Field f = byCleanUiName.get(sectionName); + com.opensr5.ini.DialogModel.Field f = byCleanUiName.get(sectionName); if (f == null) continue; String fieldName = f.getKey(); String tooltip = iniFileModel.tooltips.get(fieldName); - dialogDescription.fields.add(new FieldDescription(sectionNameWithSpecialCharacters, fieldName, fileName, tooltip)); + dialogModel.fields.add(new FieldModel(sectionNameWithSpecialCharacters, fieldName, fileName, tooltip)); File output = new File(DESTINATION + fileName); if (output == null) { @@ -201,19 +205,19 @@ public class ScreenGenerator { } } - private static void findSlices(JDialog dialog, DialogDescription dialogDescription) { + private static void findSlices(JDialog dialog, DialogModel dialogModel) { UiUtils.visitComponents(dialog, "Dynamic dialog", new Callback() { @Override public void onComponent(Component parent, Component component) { if (component instanceof JPanel) { JPanel panel = (JPanel) component; - handleBox(dialog.getTitle(), panel, dialogDescription); + handleBox(dialog.getTitle(), panel, dialogModel); } } }); } - private static void handleBox(String dialogTitle, JPanel panel, DialogDescription dialogDescription) { + private static void handleBox(String dialogTitle, JPanel panel, DialogModel dialogModel) { if (panel.getLayout() instanceof BoxLayout) { BoxLayout layout = (BoxLayout) panel.getLayout(); if (layout.getAxis() == BoxLayout.X_AXIS) @@ -244,7 +248,7 @@ public class ScreenGenerator { } }); - saveSlices(dialogTitle, yCoordinates, panelImage, dialogDescription); + saveSlices(dialogTitle, yCoordinates, panelImage, dialogModel); } } diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegraion.java b/java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegration.java similarity index 54% rename from java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegraion.java rename to java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegration.java index 0924fc7372..28b6cd6e36 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegraion.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/TunerStudioIntegration.java @@ -5,15 +5,29 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; -public class TunerStudioIntegraion { +public class TunerStudioIntegration { + /** + * these magic class names are specific to TS build + * At the moment we use 3.1.02 names + * http://www.tunerstudio.com/downloads2/TunerStudioMS_Setup_v3.1.02.exe + */ + private static final String VERSION = "3.1.02"; + private static final String TS_DIALOG = "com.efiAnalytics.ui.dg"; + private static final String TS_POPUP_MAIN_MENU = "aH.gc"; + private static final String TUNER_STUDIO = "TunerStudio"; + static Frame findMainFrame() throws InterruptedException { while (true) { Frame[] all = JFrame.getFrames(); for (Frame frame : all) { - System.out.println("I see " + frame.getTitle()); - - if (frame.getTitle().contains("TunerStudio")) { + String frameTitle = frame.getTitle(); + System.out.println("I see " + frameTitle); + if (frameTitle.contains(TUNER_STUDIO)) { + if (!frameTitle.contains(VERSION)) { + System.out.println("Title does not look right " + frameTitle + " not " + VERSION); + System.exit(-1); + } return frame; } } @@ -28,7 +42,7 @@ public class TunerStudioIntegraion { static java.util.List findMenuItems(Frame frame) { List menuItems = new ArrayList<>(); UiUtils.visitComponents(frame, "Just clicked ", (parent, component) -> { - if (component instanceof JMenuItem && component.getClass().getName().endsWith("aH.gc")) { + if (component instanceof JMenuItem && component.getClass().getName().endsWith(TS_POPUP_MAIN_MENU)) { JMenuItem menuItem = (JMenuItem) component; System.out.println("Menu item " + menuItem.getText()); menuItems.add(menuItem); @@ -39,7 +53,7 @@ public class TunerStudioIntegraion { static JDialog findDynamicDialog() { for (Window d : Dialog.getWindows()) { - if (d.getClass().getName().equals(ScreenGenerator.TS_DIALOG) && d.isVisible()) { + if (d.getClass().getName().equals(TS_DIALOG) && d.isVisible()) { return (JDialog) d; } } diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/Content.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/Content.java deleted file mode 100644 index ee3e512eda..0000000000 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/Content.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.rusefi.xml; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; -import java.util.ArrayList; -import java.util.List; - -@XmlRootElement -public class Content { - private List menus = new ArrayList<>(); - - @XmlElementWrapper - @XmlElement(name = "keyword") - public List getTopLevelMenus() { - return menus; - } -} diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/ContentModel.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/ContentModel.java new file mode 100644 index 0000000000..b6dd923368 --- /dev/null +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/ContentModel.java @@ -0,0 +1,27 @@ +package com.rusefi.xml; + +import com.rusefi.ScreenGenerator; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@XmlRootElement +public class ContentModel { + private List menus = new ArrayList<>(); + + @XmlElementWrapper + @XmlElement(name = "keyword") + public List getTopLevelMenus() { + return menus; + } + + @XmlAttribute + public String getVersion() { + return "Generated by " + ScreenGenerator.class + " on " + new Date(); + } +} diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogDescription.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogModel.java similarity index 59% rename from java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogDescription.java rename to java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogModel.java index 6be150a835..060c9196f1 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogDescription.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/DialogModel.java @@ -6,14 +6,21 @@ import javax.xml.bind.annotation.XmlElementWrapper; import java.util.ArrayList; import java.util.List; -public class DialogDescription { +public class DialogModel { private final String dialogTitle; + private final String imageName; @XmlElementWrapper @XmlElement(name = "field") - public List fields = new ArrayList<>(); + public List fields = new ArrayList<>(); - public DialogDescription(String dialogTitle) { + public DialogModel(String dialogTitle, String imageName) { this.dialogTitle = dialogTitle; + this.imageName = imageName; + } + + @XmlAttribute + public String getImageName() { + return imageName; } @XmlAttribute diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldDescription.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldModel.java similarity index 69% rename from java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldDescription.java rename to java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldModel.java index 9e2f2ab0ae..abdd1aa81f 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldDescription.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/FieldModel.java @@ -2,17 +2,17 @@ package com.rusefi.xml; import javax.xml.bind.annotation.XmlAttribute; -public class FieldDescription { +public class FieldModel { private final String uiName; private final String fieldName; - private final String fileName; + private final String imageName; private final String tooltip; - public FieldDescription(String uiName, String fieldName, String fileName, String tooltip) { + public FieldModel(String uiName, String fieldName, String fileName, String tooltip) { this.uiName = uiName; this.fieldName = fieldName; - this.fileName = fileName; + this.imageName = fileName; this.tooltip = tooltip == null ? "" : tooltip; } @@ -27,8 +27,8 @@ public class FieldDescription { } @XmlAttribute - public String getFileName() { - return fileName; + public String getImageName() { + return imageName; } @XmlAttribute diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenu.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenuModel.java similarity index 56% rename from java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenu.java rename to java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenuModel.java index dadf08c61b..b0752e9107 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenu.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/TopLevelMenuModel.java @@ -6,15 +6,17 @@ import javax.xml.bind.annotation.XmlElementWrapper; import java.util.ArrayList; import java.util.List; -public class TopLevelMenu { +public class TopLevelMenuModel { private final String title; + private final String imageName; @XmlElementWrapper @XmlElement(name = "dialog") - private List dialogs = new ArrayList<>(); + private List dialogs = new ArrayList<>(); - public TopLevelMenu(String title) { + public TopLevelMenuModel(String title, String imageName) { this.title = title; + this.imageName = imageName; } @XmlAttribute @@ -22,7 +24,12 @@ public class TopLevelMenu { return title; } - public List getDialogs() { + @XmlAttribute + public String getImageName() { + return imageName; + } + + public List getDialogs() { return dialogs; } } diff --git a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/XmlUtil.java b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/XmlUtil.java index 89bfc07482..54931894d0 100644 --- a/java_tools/ts_screenshots/screen/src/com/rusefi/xml/XmlUtil.java +++ b/java_tools/ts_screenshots/screen/src/com/rusefi/xml/XmlUtil.java @@ -11,17 +11,17 @@ public class XmlUtil { public static final String FILE_NAME = "output.xml"; - public static void writeXml(Content content) throws JAXBException, IOException { - JAXBContext jaxbContext = JAXBContext.newInstance(Content.class); + public static void writeXml(ContentModel contentModel) throws JAXBException, IOException { + JAXBContext jaxbContext = JAXBContext.newInstance(ContentModel.class); Marshaller marshaller = jaxbContext.createMarshaller(); StringWriter xmlWriter = new StringWriter(); - marshaller.marshal(content, xmlWriter); + marshaller.marshal(contentModel, xmlWriter); System.out.println(xmlWriter.toString()); System.out.println("Writing " + FILE_NAME); - marshaller.marshal(content, new FileWriter(FILE_NAME)); + marshaller.marshal(contentModel, new FileWriter(FILE_NAME)); System.out.println("Done " + FILE_NAME); } }