From c27dfae2bbf1f53b95f64bbf271f43c7975daa3a Mon Sep 17 00:00:00 2001 From: rusefi Date: Wed, 17 Jun 2020 23:19:07 -0400 Subject: [PATCH] TS plugin --- .../com/rusefi/autoupdate/AutoupdateUtil.java | 9 +++++++ .../models/src/com/rusefi/rusEFIVersion.java | 2 +- .../main/java/com/rusefi/CommandControl.java | 3 ++- .../main/java/com/rusefi/StartupFrame.java | 9 ++++--- .../com/rusefi/maintenance/EraseChip.java | 4 +-- .../rusefi/maintenance/ProgramSelector.java | 5 ++-- .../java/com/rusefi/ui/RecentCommands.java | 23 +++++++++--------- .../com/rusefi/ui/livedocs/LiveDocPanel.java | 8 +++--- .../main/java/com/rusefi/ui/util/UiUtils.java | 8 ------ .../com/rusefi/output/TSProjectConsumer.java | 1 - java_tools/ts_plugin/build.xml | 4 +-- .../src/com/rusefi/ts_plugin/PluginEntry.java | 15 +++++++++--- java_tools/ts_plugin_launcher/build.xml | 4 +++ .../resources/rusefi_online_color_300.png | Bin 0 -> 11071 bytes .../src/com/rusefi/ts_plugin/Updater.java | 10 +++++--- .../ts_plugin_launcher/ts_plugin_launcher.iml | 1 + misc/www/style/rusefi_online_color.png | Bin 0 -> 5423 bytes misc/www/style/rusefi_online_mono.png | Bin 0 -> 5279 bytes 18 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 java_tools/ts_plugin_launcher/resources/rusefi_online_color_300.png create mode 100644 misc/www/style/rusefi_online_color.png create mode 100644 misc/www/style/rusefi_online_mono.png diff --git a/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java index 98da480d4d..f863098194 100644 --- a/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java +++ b/java_console/autoupdate/src/com/rusefi/autoupdate/AutoupdateUtil.java @@ -94,6 +94,15 @@ public class AutoupdateUtil { return file.length() == completeFileSize && file.lastModified() == lastModified; } + public static ImageIcon loadIcon(String strPath) { + URL imgURL = AutoupdateUtil.class.getResource(strPath); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + return null; + } + } + public static class ConnectionAndMeta { private String zipFileName; private HttpURLConnection httpConnection; diff --git a/java_console/models/src/com/rusefi/rusEFIVersion.java b/java_console/models/src/com/rusefi/rusEFIVersion.java index 21b1ff9fb7..c6314197b6 100644 --- a/java_console/models/src/com/rusefi/rusEFIVersion.java +++ b/java_console/models/src/com/rusefi/rusEFIVersion.java @@ -3,6 +3,6 @@ package com.rusefi; import java.util.concurrent.atomic.AtomicReference; public class rusEFIVersion { - public static final int CONSOLE_VERSION = 20200614; + public static final int CONSOLE_VERSION = 20200617; public static AtomicReference firmwareVersion = new AtomicReference<>("N/A"); } diff --git a/java_console/ui/src/main/java/com/rusefi/CommandControl.java b/java_console/ui/src/main/java/com/rusefi/CommandControl.java index e8e0f70a2f..5ea082eb80 100644 --- a/java_console/ui/src/main/java/com/rusefi/CommandControl.java +++ b/java_console/ui/src/main/java/com/rusefi/CommandControl.java @@ -1,5 +1,6 @@ package com.rusefi; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.io.CommandQueue; import com.rusefi.ui.util.UiUtils; import org.jetbrains.annotations.NotNull; @@ -19,7 +20,7 @@ abstract class CommandControl { final JButton test; public CommandControl(String labelText, String iconFileName, String buttonText, JComponent... components) { - ImageIcon icon = UiUtils.loadIcon(iconFileName); + ImageIcon icon = AutoupdateUtil.loadIcon(iconFileName); JPanel rightVerticalPanel = new JPanel(new VerticalFlowLayout()); rightVerticalPanel.add(new JLabel(labelText)); for (JComponent component : components) diff --git a/java_console/ui/src/main/java/com/rusefi/StartupFrame.java b/java_console/ui/src/main/java/com/rusefi/StartupFrame.java index a3e7958366..a268b0f4ba 100644 --- a/java_console/ui/src/main/java/com/rusefi/StartupFrame.java +++ b/java_console/ui/src/main/java/com/rusefi/StartupFrame.java @@ -1,6 +1,7 @@ package com.rusefi; import com.rusefi.autodetect.PortDetector; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.io.LinkManager; import com.rusefi.io.serial.BaudRateHolder; import com.rusefi.maintenance.*; @@ -37,7 +38,7 @@ import static javax.swing.JOptionPane.YES_NO_OPTION; public class StartupFrame { // todo: figure out a better way to work with absolute path private static final String APPICON = "appicon.png"; - private static final String LOGO = "logo.gif"; + private static final String LOGO = "/com/rusefi/logo.gif"; public static final String LINK_TEXT = "rusEFI (c) 2012-2020"; private static final String URI = "http://rusefi.com/?java_console"; // private static final int RUSEFI_ORANGE = 0xff7d03; @@ -84,7 +85,7 @@ public class StartupFrame { } public static void setAppIcon(JFrame frame) { - ImageIcon icon = UiUtils.loadIcon(APPICON); + ImageIcon icon = AutoupdateUtil.loadIcon(APPICON); if (icon != null) frame.setIconImage(icon.getImage()); } @@ -217,7 +218,7 @@ public class StartupFrame { } public static JLabel createLogoLabel() { - ImageIcon logoIcon = UiUtils.loadIcon(LOGO); + ImageIcon logoIcon = AutoupdateUtil.loadIcon(LOGO); if (logoIcon == null) return null; JLabel logo = new JLabel(logoIcon); @@ -272,7 +273,7 @@ public class StartupFrame { } private Component createShowDeviceManagerButton() { - JButton showDeviceManager = new JButton(UiUtils.loadIcon("DeviceManager.png")); + JButton showDeviceManager = new JButton(AutoupdateUtil.loadIcon("DeviceManager.png")); showDeviceManager.setMargin(new Insets(0, 0, 0, 0)); showDeviceManager.setToolTipText("Show Device Manager"); showDeviceManager.addActionListener(event -> { diff --git a/java_console/ui/src/main/java/com/rusefi/maintenance/EraseChip.java b/java_console/ui/src/main/java/com/rusefi/maintenance/EraseChip.java index 6a0f84f2cc..52b8bf5d0d 100644 --- a/java_console/ui/src/main/java/com/rusefi/maintenance/EraseChip.java +++ b/java_console/ui/src/main/java/com/rusefi/maintenance/EraseChip.java @@ -1,7 +1,7 @@ package com.rusefi.maintenance; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.ui.StatusWindow; -import com.rusefi.ui.util.UiUtils; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -16,7 +16,7 @@ public class EraseChip { private static final String FLASH_SIZE = "0x0100000"; private static final String ERASE_COMMAND_SUFFIX = " -c init -c targets -c \"halt\" -c \"flash erase_address 0x08000000 " + FLASH_SIZE + "\" -c shutdown"; - private final JButton button = new JButton("ST-LINK Erase Chip", UiUtils.loadIcon("/com/rusefi/erase.png")); + private final JButton button = new JButton("ST-LINK Erase Chip", AutoupdateUtil.loadIcon("/com/rusefi/erase.png")); private StatusWindow wnd = new StatusWindow(); public EraseChip() { diff --git a/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java b/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java index 253991e77d..623ed3641b 100644 --- a/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java +++ b/java_console/ui/src/main/java/com/rusefi/maintenance/ProgramSelector.java @@ -1,13 +1,12 @@ package com.rusefi.maintenance; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.ui.util.URLLabel; -import com.rusefi.ui.util.UiUtils; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.net.URI; import java.util.Arrays; import static com.rusefi.ui.storage.PersistentConfiguration.getConfig; @@ -38,7 +37,7 @@ public class ProgramSelector { mode.setSelectedItem(persistedMode); JButton updateFirmware = new JButton("Update Firmware", - UiUtils.loadIcon("/com/rusefi/upload48.jpg")); + AutoupdateUtil.loadIcon("/com/rusefi/upload48.jpg")); controls.add(updateFirmware); JButton updateHelp = new JButton("?"); updateHelp.addActionListener(e -> URLLabel.open(HELP)); diff --git a/java_console/ui/src/main/java/com/rusefi/ui/RecentCommands.java b/java_console/ui/src/main/java/com/rusefi/ui/RecentCommands.java index a039407eb7..5338d41103 100644 --- a/java_console/ui/src/main/java/com/rusefi/ui/RecentCommands.java +++ b/java_console/ui/src/main/java/com/rusefi/ui/RecentCommands.java @@ -2,6 +2,7 @@ package com.rusefi.ui; import com.rusefi.AverageAnglesUtil; import com.rusefi.FileLog; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.config.generated.Fields; import com.rusefi.core.MessagesCentral; import com.rusefi.io.CommandQueue; @@ -54,28 +55,28 @@ public class RecentCommands { private final static Map COMMAND_ICONS = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); static { - COMMAND_ICONS.put(STOPENGINE, UiUtils.loadIcon("stop.jpg")); - ImageIcon infoIcon = UiUtils.loadIcon("info.png"); + COMMAND_ICONS.put(STOPENGINE, AutoupdateUtil.loadIcon("stop.jpg")); + ImageIcon infoIcon = AutoupdateUtil.loadIcon("info.png"); COMMAND_ICONS.put(SHOWCONFIG, infoIcon); - COMMAND_ICONS.put(HELP, UiUtils.loadIcon("help.jpg")); + COMMAND_ICONS.put(HELP, AutoupdateUtil.loadIcon("help.jpg")); COMMAND_ICONS.put(ANALOGINFO, infoIcon); - COMMAND_ICONS.put(CMD_TRIGGERINFO, UiUtils.loadIcon("trigger.jpg")); + COMMAND_ICONS.put(CMD_TRIGGERINFO, AutoupdateUtil.loadIcon("trigger.jpg")); COMMAND_ICONS.put(IDLEINFO, infoIcon); - COMMAND_ICONS.put(ALTINFO, UiUtils.loadIcon("alternator.jpg")); + COMMAND_ICONS.put(ALTINFO, AutoupdateUtil.loadIcon("alternator.jpg")); COMMAND_ICONS.put(ACCELINFO, infoIcon); COMMAND_ICONS.put(TSINFO, infoIcon); COMMAND_ICONS.put(TPSINFO, infoIcon); COMMAND_ICONS.put(MAPINFO, infoIcon); - COMMAND_ICONS.put(joystickINFO, UiUtils.loadIcon("joystick.png")); + COMMAND_ICONS.put(joystickINFO, AutoupdateUtil.loadIcon("joystick.png")); COMMAND_ICONS.put(CANINFO, infoIcon); COMMAND_ICONS.put(FUELINFO, infoIcon); COMMAND_ICONS.put(TEMPINFO, infoIcon); - COMMAND_ICONS.put(HIPINFO, UiUtils.loadIcon("knock.jpg")); - COMMAND_ICONS.put(SDINFO, UiUtils.loadIcon("sdinfo.jpg")); + COMMAND_ICONS.put(HIPINFO, AutoupdateUtil.loadIcon("knock.jpg")); + COMMAND_ICONS.put(SDINFO, AutoupdateUtil.loadIcon("sdinfo.jpg")); COMMAND_ICONS.put(FSIOINFO, infoIcon); COMMAND_ICONS.put(PINS, infoIcon); - COMMAND_ICONS.put(Fields.CMD_WRITECONFIG, UiUtils.loadIcon("writeconfig.jpg")); - COMMAND_ICONS.put(SPEEDINFO, UiUtils.loadIcon("speedinfo.jpg")); + COMMAND_ICONS.put(Fields.CMD_WRITECONFIG, AutoupdateUtil.loadIcon("writeconfig.jpg")); + COMMAND_ICONS.put(SPEEDINFO, AutoupdateUtil.loadIcon("speedinfo.jpg")); } private final JPanel content = new JPanel(new GridLayout(NUMBER_OF_COMMANDS + 1, 1)); @@ -167,7 +168,7 @@ public class RecentCommands { if (LinkManager.isLogViewer()) content.add(createButton()); - JButton reset = new JButton(UiUtils.loadIcon("undo.jpg")); + JButton reset = new JButton(AutoupdateUtil.loadIcon("undo.jpg")); reset.setContentAreaFilled(false); reset.setFocusPainted(false); reset.setBorder(BorderFactory.createEmptyBorder()); diff --git a/java_console/ui/src/main/java/com/rusefi/ui/livedocs/LiveDocPanel.java b/java_console/ui/src/main/java/com/rusefi/ui/livedocs/LiveDocPanel.java index 4900880231..e61104ae2e 100644 --- a/java_console/ui/src/main/java/com/rusefi/ui/livedocs/LiveDocPanel.java +++ b/java_console/ui/src/main/java/com/rusefi/ui/livedocs/LiveDocPanel.java @@ -1,6 +1,7 @@ package com.rusefi.ui.livedocs; import com.opensr5.ConfigurationImage; +import com.rusefi.autoupdate.AutoupdateUtil; import com.rusefi.binaryprotocol.BinaryProtocol; import com.rusefi.config.Field; import com.rusefi.config.generated.Fields; @@ -11,7 +12,6 @@ import com.rusefi.ldmp.generated.*; import com.opensr5.ini.DialogModel; import com.opensr5.ini.IniFileModel; import com.rusefi.ui.livedocs.controls.Toolbox; -import com.rusefi.ui.util.UiUtils; import com.rusefi.ui.widgets.DetachedSensor; import net.miginfocom.swing.MigLayout; import org.jetbrains.annotations.NotNull; @@ -78,7 +78,7 @@ public class LiveDocPanel { LiveDataContext context = getFieldContext(defaultContext, request.getStateContext()); Field field = getField(defaultContext, request); JLabel label = new LessJumpyJLabel("*"); - label.setIcon(UiUtils.loadIcon("livedocs/variable.png")); + label.setIcon(AutoupdateUtil.loadIcon("livedocs/variable.png")); label.setToolTipText("Variable " + field.getName()); result.addControl(label); result.actionsListAdd(context, new RefreshActions() { @@ -94,7 +94,7 @@ public class LiveDocPanel { Field field = Field.findField(Fields.VALUES, settingsInstancePrefix, request.getField()); JLabel label = new LessJumpyJLabel("*"); - label.setIcon(UiUtils.loadIcon("livedocs/setting.png")); + label.setIcon(AutoupdateUtil.loadIcon("livedocs/setting.png")); label.setToolTipText(getTooltipText(field.getName())); result.addControl(label); // todo: use different notification flow altogether since configuration has nothing to do with live data structures @@ -110,7 +110,7 @@ public class LiveDocPanel { SensorRequest request = (SensorRequest) r; Sensor sensor = Sensor.find(request.getValue()); JLabel label = new LessJumpyJLabel("*"); - label.setIcon(UiUtils.loadIcon("livedocs/gauge.png")); + label.setIcon(AutoupdateUtil.loadIcon("livedocs/gauge.png")); label.setToolTipText("Sensor " + request.getValue()); label.addMouseListener(new MouseAdapter() { @Override diff --git a/java_console/ui/src/main/java/com/rusefi/ui/util/UiUtils.java b/java_console/ui/src/main/java/com/rusefi/ui/util/UiUtils.java index 0b7d58852f..5fc930d18a 100644 --- a/java_console/ui/src/main/java/com/rusefi/ui/util/UiUtils.java +++ b/java_console/ui/src/main/java/com/rusefi/ui/util/UiUtils.java @@ -124,14 +124,6 @@ public class UiUtils { return imageButton; } - public static ImageIcon loadIcon(String strPath) { - URL imgURL = StartupFrame.class.getResource(strPath); - if (imgURL != null) - return new ImageIcon(imgURL); - else - return null; - } - public static void invokeAndWait(Runnable runnable) throws InterruptedException, InvocationTargetException { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); diff --git a/java_tools/configuration_definition/src/com/rusefi/output/TSProjectConsumer.java b/java_tools/configuration_definition/src/com/rusefi/output/TSProjectConsumer.java index 28891549d9..5e33646a89 100644 --- a/java_tools/configuration_definition/src/com/rusefi/output/TSProjectConsumer.java +++ b/java_tools/configuration_definition/src/com/rusefi/output/TSProjectConsumer.java @@ -1,6 +1,5 @@ package com.rusefi.output; -import com.opensr5.ini.RawIniFile; import com.rusefi.*; import com.rusefi.util.LazyFile; import com.rusefi.util.Output; diff --git a/java_tools/ts_plugin/build.xml b/java_tools/ts_plugin/build.xml index cc351ad1b0..faffb95faa 100644 --- a/java_tools/ts_plugin/build.xml +++ b/java_tools/ts_plugin/build.xml @@ -31,12 +31,12 @@ - + - + diff --git a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java index 351dd85f47..871665ee2e 100644 --- a/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java +++ b/java_tools/ts_plugin/src/com/rusefi/ts_plugin/PluginEntry.java @@ -16,6 +16,7 @@ import javax.xml.bind.JAXBException; import java.awt.event.ActionEvent; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.Map; import java.util.TreeMap; import java.util.jar.Attributes; @@ -144,10 +145,18 @@ public class PluginEntry implements TsPluginBody { */ @SuppressWarnings("unused") public static String getVersion() { + // all this magic below to make sure we are reading manifest of the *our* jar file not TS main jar file + Class clazz = PluginEntry.class; + String className = clazz.getSimpleName() + ".class"; + String classPath = clazz.getResource(className).toString(); + if (!classPath.startsWith("jar")) { + // Class not from JAR + return "Local Run"; + } + String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + + "/META-INF/MANIFEST.MF"; try { - InputStream stream = PluginEntry.class.getResourceAsStream("/META-INF/MANIFEST.MF"); - Manifest manifest = new Manifest(stream); - + Manifest manifest = new Manifest(new URL(manifestPath).openStream()); Attributes attributes = manifest.getMainAttributes(); System.out.println("Attributed " + attributes); System.out.println("Attributed " + attributes.keySet()); diff --git a/java_tools/ts_plugin_launcher/build.xml b/java_tools/ts_plugin_launcher/build.xml index 16f65b82da..8a35f07e66 100644 --- a/java_tools/ts_plugin_launcher/build.xml +++ b/java_tools/ts_plugin_launcher/build.xml @@ -24,6 +24,10 @@ + + + + diff --git a/java_tools/ts_plugin_launcher/resources/rusefi_online_color_300.png b/java_tools/ts_plugin_launcher/resources/rusefi_online_color_300.png new file mode 100644 index 0000000000000000000000000000000000000000..58f988100a055931e2d43df577186724b23c4f4c GIT binary patch literal 11071 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 + diff --git a/misc/www/style/rusefi_online_color.png b/misc/www/style/rusefi_online_color.png new file mode 100644 index 0000000000000000000000000000000000000000..ddc2633eca79b47823d18eaf6e1f86c08a1b226c GIT binary patch literal 5423 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 S@Ebe<1uj_Fo~tyw{@`CpoOF}` literal 0 HcmV?d00001 diff --git a/misc/www/style/rusefi_online_mono.png b/misc/www/style/rusefi_online_mono.png new file mode 100644 index 0000000000000000000000000000000000000000..6a460aafaa649a39951c8bfccb37e79fc79e8be7 GIT binary patch literal 5279 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 CH{Ct} literal 0 HcmV?d00001