screen generator progress
This commit is contained in:
parent
eb480c8cc7
commit
4e115c12c1
|
@ -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<AbstractButton> 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<String, DialogModel.Field> byCleanUiName = new TreeMap<>();
|
||||
static Map<String, com.opensr5.ini.DialogModel.Field> 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<String, DialogModel.Field> a : iniFileModel.getAllFields().entrySet()) {
|
||||
for (Map.Entry<String, com.opensr5.ini.DialogModel.Field> 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<AbstractButton> 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<JMenuItem> menuItems = TunerStudioIntegraion.findMenuItems(frame);
|
||||
List<JMenuItem> 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<JDialog> 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<Integer, String> yCoordinates, BufferedImage dialogScreenShot, DialogDescription dialogDescription) {
|
||||
private static void saveSlices(String dialogTitle, Map<Integer, String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<JMenuItem> findMenuItems(Frame frame) {
|
||||
List<JMenuItem> 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;
|
||||
}
|
||||
}
|
|
@ -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<TopLevelMenu> menus = new ArrayList<>();
|
||||
|
||||
@XmlElementWrapper
|
||||
@XmlElement(name = "keyword")
|
||||
public List<TopLevelMenu> getTopLevelMenus() {
|
||||
return menus;
|
||||
}
|
||||
}
|
|
@ -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<TopLevelMenuModel> menus = new ArrayList<>();
|
||||
|
||||
@XmlElementWrapper
|
||||
@XmlElement(name = "keyword")
|
||||
public List<TopLevelMenuModel> getTopLevelMenus() {
|
||||
return menus;
|
||||
}
|
||||
|
||||
@XmlAttribute
|
||||
public String getVersion() {
|
||||
return "Generated by " + ScreenGenerator.class + " on " + new Date();
|
||||
}
|
||||
}
|
|
@ -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<FieldDescription> fields = new ArrayList<>();
|
||||
public List<FieldModel> 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
|
|
@ -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
|
|
@ -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<DialogDescription> dialogs = new ArrayList<>();
|
||||
private List<DialogModel> 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<DialogDescription> getDialogs() {
|
||||
@XmlAttribute
|
||||
public String getImageName() {
|
||||
return imageName;
|
||||
}
|
||||
|
||||
public List<DialogModel> getDialogs() {
|
||||
return dialogs;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue