X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fnet%2Fsf%2Fopenrocket%2Futil%2FGUIUtil.java;fp=src%2Fnet%2Fsf%2Fopenrocket%2Futil%2FGUIUtil.java;h=2f50a9cf92d11c75d2c197d3d02c6764a8b48663;hb=b3c3c1071dfdca4c6b3eb9935dc461201abdaf60;hp=27cf121c7a5ffad1ae201742e15c87cb7df226a4;hpb=fa61335265b0af5f9bc8800df953d41cde2d75f6;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/util/GUIUtil.java b/src/net/sf/openrocket/util/GUIUtil.java index 27cf121c..2f50a9cf 100644 --- a/src/net/sf/openrocket/util/GUIUtil.java +++ b/src/net/sf/openrocket/util/GUIUtil.java @@ -1,36 +1,62 @@ package net.sf.openrocket.util; import java.awt.Component; +import java.awt.Container; import java.awt.Image; import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Window; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentListener; +import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.Vector; import javax.imageio.ImageIO; import javax.swing.AbstractAction; +import javax.swing.AbstractButton; import javax.swing.Action; +import javax.swing.DefaultBoundedRangeModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListSelectionModel; import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JRootPane; +import javax.swing.JSlider; +import javax.swing.JSpinner; import javax.swing.JTable; +import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.RootPaneContainer; +import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; +import javax.swing.event.ChangeListener; import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableColumnModel; +import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.DefaultTreeSelectionModel; +import javax.swing.tree.TreeNode; + +import net.sf.openrocket.gui.Resettable; public class GUIUtil { @@ -45,7 +71,6 @@ public class GUIUtil { loadImage("pix/icon/icon-032.png"); loadImage("pix/icon/icon-016.png"); } - private static void loadImage(String file) { InputStream is; @@ -62,6 +87,26 @@ public class GUIUtil { } + + /** + * Set suitable options for a single-use disposable dialog. This includes + * setting ESC to close the dialog and adding the appropriate window icons. + * If defaultButton is provided, it is set to the default button action. + *
+ * The default button must be already attached to the dialog.
+ *
+ * @param dialog the dialog.
+ * @param defaultButton the default button of the dialog, or null
.
+ */
+ public static void setDisposableDialogOptions(JDialog dialog, JButton defaultButton) {
+ installEscapeCloseOperation(dialog);
+ setWindowIcons(dialog);
+ addModelNullingListener(dialog);
+ if (defaultButton != null) {
+ setDefaultButton(defaultButton);
+ }
+ }
+
/**
@@ -115,10 +160,165 @@ public class GUIUtil {
}
+
+ /**
+ * Set the OpenRocket icons to the window icons.
+ *
+ * @param window the window to set.
+ */
public static void setWindowIcons(Window window) {
window.setIconImages(images);
}
+ /**
+ * Add a listener to the provided window that will call {@link #setNullModels(Component)}
+ * on the window once it is disposed. This method may only be used on single-use
+ * windows and dialogs, that will never be shown again once closed!
+ *
+ * @param window the window to add the listener to.
+ */
+ public static void addModelNullingListener(final Window window) {
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) {
+ setNullModels(window);
+ }
+ });
+ }
+
+
+ /**
+ * Traverses recursively the component tree, and sets all applicable component
+ * models to null, so as to remove the listener connections. After calling this
+ * method the component hierarchy should no longed be used.
+ *
+ * All components that use custom models should be added to this method, as
+ * there exists no standard way of removing the model from a component.
+ *
+ * @param c the component (null
is ok)
+ */
+ public static void setNullModels(Component c) {
+ if (c==null)
+ return;
+
+ // Remove various listeners
+ for (ComponentListener l: c.getComponentListeners()) {
+ c.removeComponentListener(l);
+ }
+ for (FocusListener l: c.getFocusListeners()) {
+ c.removeFocusListener(l);
+ }
+ for (MouseListener l: c.getMouseListeners()) {
+ c.removeMouseListener(l);
+ }
+ for (PropertyChangeListener l: c.getPropertyChangeListeners()) {
+ c.removePropertyChangeListener(l);
+ }
+ for (PropertyChangeListener l: c.getPropertyChangeListeners("model")) {
+ c.removePropertyChangeListener("model", l);
+ }
+ for (PropertyChangeListener l: c.getPropertyChangeListeners("action")) {
+ c.removePropertyChangeListener("action", l);
+ }
+
+ // Remove models for known components
+ // Why the FSCK must this be so hard?!?!?
+
+ if (c instanceof JSpinner) {
+
+ JSpinner spinner = (JSpinner)c;
+ for (ChangeListener l: spinner.getChangeListeners()) {
+ spinner.removeChangeListener(l);
+ }
+ spinner.setModel(new SpinnerNumberModel());
+
+ } else if (c instanceof JSlider) {
+
+ JSlider slider = (JSlider)c;
+ for (ChangeListener l: slider.getChangeListeners()) {
+ slider.removeChangeListener(l);
+ }
+ slider.setModel(new DefaultBoundedRangeModel());
+
+ } else if (c instanceof JComboBox) {
+
+ JComboBox combo = (JComboBox)c;
+ for (ActionListener l: combo.getActionListeners()) {
+ combo.removeActionListener(l);
+ }
+ combo.setModel(new DefaultComboBoxModel());
+
+ } else if (c instanceof AbstractButton) {
+
+ AbstractButton button = (AbstractButton)c;
+ for (ActionListener l: button.getActionListeners()) {
+ button.removeActionListener(l);
+ }
+ button.setAction(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) { }
+ });
+
+ } else if (c instanceof JTable) {
+
+ JTable table = (JTable)c;
+ table.setModel(new DefaultTableModel());
+ table.setColumnModel(new DefaultTableColumnModel());
+ table.setSelectionModel(new DefaultListSelectionModel());
+
+ } else if (c instanceof JTree) {
+
+ JTree tree = (JTree)c;
+ tree.setModel(new DefaultTreeModel(new TreeNode() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration children() {
+ return new Vector().elements();
+ }
+ @Override
+ public boolean getAllowsChildren() {
+ return false;
+ }
+ @Override
+ public TreeNode getChildAt(int childIndex) {
+ return null;
+ }
+ @Override
+ public int getChildCount() {
+ return 0;
+ }
+ @Override
+ public int getIndex(TreeNode node) {
+ return 0;
+ }
+ @Override
+ public TreeNode getParent() {
+ return null;
+ }
+ @Override
+ public boolean isLeaf() {
+ return true;
+ }
+ }));
+ tree.setSelectionModel(new DefaultTreeSelectionModel());
+
+ } else if (c instanceof Resettable) {
+
+ ((Resettable)c).resetModel();
+
+ }
+
+ // Recurse the component
+ if (c instanceof Container) {
+ Component[] cs = ((Container)c).getComponents();
+ for (Component sub: cs)
+ setNullModels(sub);
+ }
+
+ }
+
+
+
/**
* A mouse listener that toggles the state of a boolean value in a table model
@@ -184,5 +384,5 @@ public class GUIUtil {
}
}
-
+
}