diff --git a/src/main/java/net/vhati/modmanager/ui/InertPanel.java b/src/main/java/net/vhati/modmanager/ui/InertPanel.java new file mode 100644 index 0000000..4db75ee --- /dev/null +++ b/src/main/java/net/vhati/modmanager/ui/InertPanel.java @@ -0,0 +1,55 @@ +package net.vhati.modmanager.ui; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.KeyEventDispatcher; +import java.awt.KeyboardFocusManager; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + + +/** + * A panel that consumes all mouse/keyboard events, for use as a glass pane. + */ +public class InertPanel extends JPanel { + + private KeyEventDispatcher nullDispatcher; + + + public InertPanel() { + super(); + + nullDispatcher = new KeyEventDispatcher() { + @Override + public boolean dispatchKeyEvent( KeyEvent e ) { + return InertPanel.this == ( (JFrame)SwingUtilities.getWindowAncestor( (Component)e.getSource() ) ).getGlassPane(); + } + }; + + this.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed( MouseEvent e ) {e.consume();} + @Override + public void mouseReleased( MouseEvent e ) {e.consume();} + }); + + this.setCursor(Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR )); + this.setOpaque( false ); + } + + + @Override + public void setVisible( boolean b ) { + super.setVisible( b ); + if ( b ) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( nullDispatcher ); + } else { + KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher( nullDispatcher ); + } + } +} diff --git a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java index 23d30da..3d81135 100644 --- a/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java +++ b/src/main/java/net/vhati/modmanager/ui/ManagerFrame.java @@ -72,6 +72,7 @@ import net.vhati.modmanager.core.Report.ReportFormatter; import net.vhati.modmanager.json.GrognakCatalogFetcher; import net.vhati.modmanager.json.JacksonGrognakCatalogReader; import net.vhati.modmanager.ui.ChecklistTableModel; +import net.vhati.modmanager.ui.InertPanel; import net.vhati.modmanager.ui.ModInfoArea; import net.vhati.modmanager.ui.ModPatchDialog; import net.vhati.modmanager.ui.ModXMLSandbox; @@ -83,7 +84,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -public class ManagerFrame extends JFrame implements ActionListener, HashObserver, Statusbar { +public class ManagerFrame extends JFrame implements ActionListener, HashObserver, Nerfable, Statusbar { private static final Logger log = LogManager.getLogger(ManagerFrame.class); @@ -100,6 +101,8 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver private String appURL; private String appAuthor; + private NerfListener nerfListener = new NerfListener( this ); + private HashMap modFileHashes = new HashMap(); private ModDB modDB = new ModDB(); @@ -319,6 +322,8 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver menubar.add( helpMenu ); this.setJMenuBar( menubar ); + this.setGlassPane( new InertPanel() ); + this.setContentPane( contentPane ); this.pack(); this.setMinimumSize( new Dimension( 300, modActionsPanel.getPreferredSize().height+90 ) ); @@ -691,8 +696,11 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver File datsDir = new File( config.getProperty( "ftl_dats_path" ) ); File dataDatFile = new File( datsDir, "data.dat" ); - ModXMLSandbox sandboxDlg = new ModXMLSandbox( this, dataDatFile ); - sandboxDlg.setVisible( true ); + ModXMLSandbox sandboxFrame = new ModXMLSandbox( dataDatFile ); + sandboxFrame.addWindowListener( nerfListener ); + sandboxFrame.setSize( 800, 600 ); + sandboxFrame.setLocationRelativeTo( null ); + sandboxFrame.setVisible( true ); } else if ( source == exitMenuItem ) { setStatusText( "" ); @@ -752,6 +760,37 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver } + @Override + public void setNerfed( boolean b ) { + Component glassPane = this.getGlassPane(); + if (b) { + glassPane.setVisible(true); + glassPane.requestFocusInWindow(); + } else { + glassPane.setVisible(false); + } + } + + + + private static class NerfListener extends WindowAdapter { + private Nerfable nerfObj; + + public NerfListener( Nerfable nerfObj ) { + this.nerfObj = nerfObj; + } + + @Override + public void windowOpened( WindowEvent e ) { + nerfObj.setNerfed( true ); + } + @Override + public void windowClosing( WindowEvent e ) { + nerfObj.setNerfed( false ); + } + } + + private static class ModFileFilter implements FileFilter { boolean allowZip; diff --git a/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java b/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java index 29877d0..db800fd 100644 --- a/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java +++ b/src/main/java/net/vhati/modmanager/ui/ModXMLSandbox.java @@ -28,9 +28,9 @@ import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JSplitPane; @@ -65,7 +65,10 @@ import org.jdom2.Document; import org.jdom2.input.JDOMParseException; -public class ModXMLSandbox extends JDialog implements ActionListener { +/** + * A basic text editor to test XML modding. + */ +public class ModXMLSandbox extends JFrame implements ActionListener { private UndoManager undoManager = new UndoManager(); private Document mainDoc = null; @@ -76,6 +79,7 @@ public class ModXMLSandbox extends JDialog implements ActionListener { private JScrollPane mainScroll; private JScrollPane appendScroll; private JScrollPane resultScroll; + private JSplitPane splitPane; private JScrollPane messageScroll; private JTextArea mainArea; @@ -88,8 +92,8 @@ public class ModXMLSandbox extends JDialog implements ActionListener { private JLabel statusLbl; - public ModXMLSandbox( Frame owner, File dataDatFile ) { - super( owner, "Mod XML Sandbox", true ); + public ModXMLSandbox( File dataDatFile ) { + super( "Mod XML Sandbox" ); this.dataDatFile = dataDatFile; @@ -145,7 +149,7 @@ public class ModXMLSandbox extends JDialog implements ActionListener { topPanel.add( areasPane, BorderLayout.CENTER ); topPanel.add( ctrlPanel, BorderLayout.SOUTH ); - final JSplitPane splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT ); + splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT ); splitPane.setTopComponent( topPanel ); splitPane.setBottomComponent( messageArea ); @@ -272,15 +276,22 @@ public class ModXMLSandbox extends JDialog implements ActionListener { resultArea.addAncestorListener( new FocusAncestorListener( resultArea ) ); this.pack(); - this.setSize( 800, 600 ); - this.setLocationRelativeTo( null ); + } - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - splitPane.setDividerLocation( 0.80d ); - } - }); + + @Override + public void setVisible( boolean b ) { + super.setVisible( b ); + + if ( b ) { + // Splitpane has to be realized before the divider can be moved. + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + splitPane.setDividerLocation( 0.80d ); + } + }); + } } diff --git a/src/main/java/net/vhati/modmanager/ui/Nerfable.java b/src/main/java/net/vhati/modmanager/ui/Nerfable.java new file mode 100644 index 0000000..cba3762 --- /dev/null +++ b/src/main/java/net/vhati/modmanager/ui/Nerfable.java @@ -0,0 +1,16 @@ +package net.vhati.modmanager.ui; + + +/* + * An interface to en/disable user interaction. + * It was written with JFrames and glass panes in mind. + */ +public interface Nerfable { + + /* + * Either nerf or restore user interaction. + * + * @param b the nerfed state + */ + public void setNerfed( boolean b ); +}