Skip to content

Commit

Permalink
Merge pull request #1648 from pavelbraginskiy/drag-drop
Browse files Browse the repository at this point in the history
Allow opening unit and MUL files with MML by file association or drag-drop
  • Loading branch information
HammerGS authored Nov 4, 2024
2 parents fd8ab00 + ac1c381 commit bc48194
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 18 deletions.
2 changes: 2 additions & 0 deletions megameklab/resources/megameklab/resources/Dialogs.properties
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ ConfigurationDialog.startup.text=MML Startup:
ConfigurationDialog.startup.tooltip=Depending on the startup type selected, MML will start in the main menu or, alternatively, directly load the most recent unit or start with a new unit instead of the main menu.
ConfigurationDialog.mekChassis.text=Mek Chassis Arrangement:
ConfigurationDialog.mekChassis.tooltip=Meks with a Clan and an IS chassis name will print their chassis in the selected arrangement. Meks with no clan chassis name will always just print their chassis.
ConfigurationDialog.cbMulOpenBehaviour.text=MUL file open behaviour:
ConfigurationDialog.cbMulOpenBehaviour.tooltip=What should be done when a MUL file is dragged onto the MML window or opened with MML by the operating system?
RecordSheetTask.printing=Printing
RecordSheetTask.exporting=Exporting
Expand Down
3 changes: 3 additions & 0 deletions megameklab/resources/megameklab/resources/Menu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ MMLStartUp.NEW_JUMPSHIP=New Advanced Aerospace
MMLStartUp.NEW_SUPPORTVEE=New Support Vehicle
MMLStartUp.NEW_PROTOMEK=New ProtoMek

MulDndBehaviour.PRINT=Print
MulDndBehaviour.EXPORT=Export to PDF

# The following values are used programatically by ClanISMekNameOrdering
ClanISMekNameOrdering.CLAN_IS=Clan Name (IS Name)
ClanISMekNameOrdering.IS_CLAN=IS Name (Clan Name)
Expand Down
29 changes: 27 additions & 2 deletions megameklab/src/megameklab/MegaMekLab.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import megameklab.ui.StartupGUI;
import megameklab.ui.dialog.UiLoader;
import megameklab.util.CConfig;
import megameklab.util.UnitPrintManager;
import megameklab.util.UnitUtil;

public class MegaMekLab {
Expand Down Expand Up @@ -74,7 +75,7 @@ public static void main(String... args) {
MegaMek.initializeSuiteGraphicalSetups(MMLConstants.PROJECT_NAME);
ToolTipManager.sharedInstance().setDismissDelay(1000000);
ToolTipManager.sharedInstance().setReshowDelay(50);
startup();
startup(args);
}

public static void initializeLogging(final String originProject) {
Expand All @@ -89,7 +90,7 @@ public static String getUnderlyingInformation(final String originProject) {
return MegaMek.getUnderlyingInformation(originProject, MMLConstants.PROJECT_NAME);
}

private static void startup() {
private static void startup(String[] args) {
EquipmentType.initializeTypes();
MekSummaryCache.getInstance();
CConfig.load();
Expand All @@ -103,6 +104,30 @@ private static void startup() {

updateGuiScaling(); // also sets the look-and-feel

if (args.length == 1) {
try {
var name = args[0];
logger.info("Trying to open file {}", name);
if (name.toLowerCase().endsWith(".blk") || name.endsWith(".mtf")) {
var file = new File(name);
Entity e = new MekFileParser(file).getEntity();
if (!UnitUtil.validateUnit(e).isBlank()) {
PopupMessages.showUnitInvalidWarning(null, UnitUtil.validateUnit(e));
}
UiLoader.loadUi(e, file.toString());
return;
} else if (name.toLowerCase().endsWith(".mul")) {
SwingUtilities.invokeLater(() -> {
var frame = new JFrame();
UnitPrintManager.printMUL(frame, CConfig.getBooleanParam(CConfig.MISC_MUL_OPEN_BEHAVIOUR), new File(name));
frame.dispose();
});
}
} catch (Exception e) {
logger.warn(e);
}
}

// Create a startup frame and display it
switch (CConfig.getStartUpType()) {
case NEW_MEK -> UiLoader.loadUi(Entity.ETYPE_MEK, false, false);
Expand Down
13 changes: 10 additions & 3 deletions megameklab/src/megameklab/ui/MegaMekLabMainUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import megameklab.ui.util.ExitOnWindowClosingListener;
import megameklab.ui.util.RefreshListener;
import megameklab.util.CConfig;
import megameklab.util.MMLFileDropTarget;

import javax.swing.*;
import java.awt.*;
Expand All @@ -34,7 +35,7 @@ public abstract class MegaMekLabMainUI extends JFrame implements RefreshListener
protected MenuBar mmlMenuBar;
protected boolean refreshRequired = false;
private String originalName = "";

public MegaMekLabMainUI() {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new ExitOnWindowClosingListener(this));
Expand All @@ -46,8 +47,9 @@ protected void finishSetup() {
setJMenuBar(mmlMenuBar);
reloadTabs();
refreshAll();
this.setDropTarget(new MMLFileDropTarget(this));
}

protected void setSizeAndLocation() {
pack();
restrictToScrenSize();
Expand Down Expand Up @@ -196,4 +198,9 @@ public void refreshMenuBar() {
public boolean hasEntityNameChanged() {
return !MenuBar.createUnitFilename(entity).equals(originalName);
}
}

@Override
public MenuBar getMMLMenuBar() {
return mmlMenuBar;
}
}
4 changes: 4 additions & 0 deletions megameklab/src/megameklab/ui/MenuBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,10 @@ private void loadUnitFromFile(int fileNumber) {
}
}

loadFile(unitFile);
}

public void loadFile(File unitFile) {
try {
Entity loadedUnit = new MekFileParser(unitFile).getEntity();

Expand Down
2 changes: 2 additions & 0 deletions megameklab/src/megameklab/ui/MenuBarOwner.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,6 @@ default void changeTheme(String lookAndFeelInfo) {
}
});
}

MenuBar getMMLMenuBar();
}
33 changes: 33 additions & 0 deletions megameklab/src/megameklab/ui/MulDndBehaviour.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 - The MegaMek Team. All Rights Reserved.
*
* This file is part of MegaMekLab.
*
* MegaMek is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MegaMek is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MegaMek. If not, see <http://www.gnu.org/licenses/>.
*/
package megameklab.ui;

import java.util.ResourceBundle;

public enum MulDndBehaviour {
PRINT,
EXPORT;

private final ResourceBundle resources = ResourceBundle.getBundle("megameklab.resources.Menu");

/** @return A display name for this MMLStartUp taken from the resources (possibly localised). */
public String getDisplayName() {
return resources.getString("MulDndBehaviour." + name());
}
}
7 changes: 7 additions & 0 deletions megameklab/src/megameklab/ui/StartupGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import megameklab.ui.dialog.UiLoader;
import megameklab.ui.util.ExitOnWindowClosingListener;
import megameklab.util.CConfig;
import megameklab.util.MMLFileDropTarget;
import megameklab.util.UnitUtil;

import javax.swing.*;
Expand Down Expand Up @@ -236,6 +237,7 @@ private void initComponents() {
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
this.setDropTarget(new MMLFileDropTarget(this));
}

/**
Expand Down Expand Up @@ -314,4 +316,9 @@ public boolean hasEntityNameChanged() {
public void refreshMenuBar() {
mmlMenuBar.refreshMenuBar();
}

@Override
public MenuBar getMMLMenuBar() {
return mmlMenuBar;
}
}
35 changes: 24 additions & 11 deletions megameklab/src/megameklab/ui/dialog/settings/MiscSettingsPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,10 @@
import megamek.common.preference.PreferenceManager;
import megamek.logging.MMLogger;
import megameklab.ui.MMLStartUp;
import megameklab.ui.MulDndBehaviour;
import megameklab.ui.util.SpringUtilities;
import megameklab.util.CConfig;
import org.apache.logging.log4j.LogManager;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
Expand All @@ -64,9 +58,10 @@ public class MiscSettingsPanel extends JPanel {
private final JCheckBox chkSkipSavePrompts = new JCheckBox();
private final JTextField txtUserDir = new JTextField(20);
private final JSlider guiScale = new JSlider();
private final MMComboBox<MulDndBehaviour> cbMulOpenBehaviour = new MMComboBox<>("MUL Drag and Drop behaviour", MulDndBehaviour.values());

MiscSettingsPanel(JFrame parent) {
startUpMMComboBox.setRenderer(startUpRenderer);
startUpMMComboBox.setRenderer(miscComboBoxRenderer);
startUpMMComboBox.setSelectedItem(CConfig.getStartUpType());
startUpMMComboBox.setToolTipText(resources.getString("ConfigurationDialog.startup.tooltip"));
JLabel startUpLabel = new JLabel(resources.getString("ConfigurationDialog.startup.text"));
Expand All @@ -78,6 +73,17 @@ public class MiscSettingsPanel extends JPanel {
startUpLine.add(Box.createHorizontalStrut(5));
startUpLine.add(startUpMMComboBox);

cbMulOpenBehaviour.setRenderer(miscComboBoxRenderer);
cbMulOpenBehaviour.setToolTipText(resources.getString("ConfigurationDialog.cbMulOpenBehaviour.tooltip"));
cbMulOpenBehaviour.setSelectedItem(CConfig.getBooleanParam(CConfig.MISC_MUL_OPEN_BEHAVIOUR) ? MulDndBehaviour.EXPORT : MulDndBehaviour.PRINT);
JLabel mulOpenLabel = new JLabel(resources.getString("ConfigurationDialog.cbMulOpenBehaviour.text"));
mulOpenLabel.setToolTipText(resources.getString("ConfigurationDialog.cbMulOpenBehaviour.tooltip"));

JPanel mulOpenLine = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
mulOpenLine.add(mulOpenLabel);
mulOpenLine.add(Box.createHorizontalStrut(5));
mulOpenLine.add(cbMulOpenBehaviour);

chkSummaryFormatTRO.setText(resources.getString("ConfigurationDialog.chkSummaryFormatTRO.text"));
chkSummaryFormatTRO.setToolTipText(resources.getString("ConfigurationDialog.chkSummaryFormatTRO.tooltip"));

Expand Down Expand Up @@ -136,11 +142,12 @@ public class MiscSettingsPanel extends JPanel {
JPanel gridPanel = new JPanel(new SpringLayout());
gridPanel.add(startUpLine);
gridPanel.add(userDirLine);
gridPanel.add(mulOpenLine);
gridPanel.add(chkSummaryFormatTRO);
gridPanel.add(chkSkipSavePrompts);
gridPanel.add(scaleLine);

SpringUtilities.makeCompactGrid(gridPanel, 5, 1, 0, 0, 15, 10);
SpringUtilities.makeCompactGrid(gridPanel, 6, 1, 0, 0, 15, 10);
gridPanel.setBorder(new EmptyBorder(20, 30, 20, 30));
setLayout(new FlowLayout(FlowLayout.LEFT));
add(gridPanel);
Expand All @@ -154,6 +161,7 @@ Map<String, String> getMiscSettings() {
? MMLStartUp.SPLASH_SCREEN
: startUpMMComboBox.getSelectedItem();
miscSettings.put(CConfig.MISC_STARTUP, startUp.name());
miscSettings.put(CConfig.MISC_MUL_OPEN_BEHAVIOUR, String.valueOf(cbMulOpenBehaviour.getSelectedItem() == MulDndBehaviour.EXPORT));
// User directory and gui scale are stored in MM's client settings, not in CConfig, therefore not added here
return miscSettings;
}
Expand All @@ -166,7 +174,7 @@ float guiScale() {
return 0.1f * guiScale.getValue();
}

DefaultListCellRenderer startUpRenderer = new DefaultListCellRenderer() {
DefaultListCellRenderer miscComboBoxRenderer = new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
Expand All @@ -175,6 +183,11 @@ public Component getListCellRendererComponent(JList<?> list, Object value, int i
};

private String displayName(Object value) {
return (value instanceof MMLStartUp) ? ((MMLStartUp) value).getDisplayName() : "";
if (value instanceof MMLStartUp su) {
return su.getDisplayName();
} else if (value instanceof MulDndBehaviour mdb) {
return mdb.getDisplayName();
}
return "";
}
}
1 change: 1 addition & 0 deletions megameklab/src/megameklab/util/CConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public final class CConfig {
public static final String MISC_STARTUP = "StartupGui";
public static final String MISC_SUMMARY_FORMAT_TRO = "useTROFormat";
public static final String MISC_SKIP_SAFETY_PROMPTS = "skipSafetyPrompts";
public static final String MISC_MUL_OPEN_BEHAVIOUR = "mulDndBehaviour";

public static final String GUI_PLAF = "lookAndFeel";
public static final String GUI_COLOR_WEAPONS = "Weapons";
Expand Down
70 changes: 70 additions & 0 deletions megameklab/src/megameklab/util/MMLFileDropTarget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2024 - The MegaMek Team. All Rights Reserved.
*
* This file is part of MegaMekLab.
*
* MegaMek is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MegaMek is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MegaMek. If not, see <http://www.gnu.org/licenses/>.
*/

package megameklab.util;

import megamek.logging.MMLogger;
import megameklab.ui.MenuBarOwner;

import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.util.List;

public class MMLFileDropTarget extends DropTarget {
private static final MMLogger logger = MMLogger.create(MMLFileDropTarget.class);

private final MenuBarOwner owner;

public MMLFileDropTarget(MenuBarOwner owner) {
this.owner = owner;
}

@Override
public synchronized void drop(DropTargetDropEvent event) {
try {
event.acceptDrop(DnDConstants.ACTION_COPY);
var files = (List<File>) event.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
if (files.size() != 1) {
event.dropComplete(false);
return;
}

var file = files.get(0);
var name = file.getName();

if (name.toLowerCase().endsWith(".mtf") || name.toLowerCase().endsWith(".blk")) {
owner.getMMLMenuBar().loadFile(file);
event.dropComplete(true);
} else if (name.toLowerCase().endsWith(".mul")) {
UnitPrintManager.printMUL(owner.getFrame(), CConfig.getBooleanParam(CConfig.MISC_MUL_OPEN_BEHAVIOUR), file);
event.dropComplete(true);
} else {
event.dropComplete(false);
}


} catch (Exception e) {
event.dropComplete(false);
logger.warn(e);
}
}
}
8 changes: 6 additions & 2 deletions megameklab/src/megameklab/util/UnitPrintManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,24 @@ public static void printMUL(JFrame parent, boolean printToPdf) {
// I want a file, y'know!
return;
}
printMUL(parent, printToPdf, f.getSelectedFile());
}

public static void printMUL(JFrame parent, boolean printToPdf, File file) {
Vector<Entity> loadedUnits;
try {
var options = new GameOptions();
options.initialize();
options.getOption(RPG_MANEI_DOMINI).setValue(true);
options.getOption(RPG_PILOT_ADVANTAGES).setValue(true);
loadedUnits = new MULParser(f.getSelectedFile(), options).getEntities();
loadedUnits = new MULParser(file, options).getEntities();
loadedUnits.trimToSize();
} catch (Exception ex) {
logger.error("", ex);
return;
}

new PrintQueueDialog(parent, printToPdf, loadedUnits, true, f.getSelectedFile().getName()).setVisible(true);
new PrintQueueDialog(parent, printToPdf, loadedUnits, true, file.getName()).setVisible(true);
}

public static File getExportFile(Frame parent) {
Expand Down

0 comments on commit bc48194

Please sign in to comment.