// Near Infinity - An Infinity Engine Browser and Editor // Copyright (C) 2001 - 2005 Jon Olav Hauglid // See LICENSE.txt for license information package org.infinity.gui; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.AbstractAction; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import org.infinity.NearInfinity; import org.infinity.resource.Closeable; public class ChildFrame extends JFrame { private static final List<ChildFrame> windows = new ArrayList<ChildFrame>(); private final boolean closeOnInvisible; public static void closeWindow(Class<ChildFrame> frameClass) { WindowEvent event = new WindowEvent(NearInfinity.getInstance(), WindowEvent.WINDOW_CLOSING); for (Iterator<ChildFrame> i = windows.iterator(); i.hasNext();) { ChildFrame frame = i.next(); if (frame.getClass() == frameClass) { i.remove(); try { frame.windowClosing(true); frame.setVisible(false); WindowListener listeners[] = frame.getWindowListeners(); for (final WindowListener listener : listeners) { listener.windowClosing(event); } if (frame instanceof Closeable) { frame.close(); } frame.dispose(); } catch (Exception e) { e.printStackTrace(); } } } } public static void closeWindows() { WindowEvent event = new WindowEvent(NearInfinity.getInstance(), WindowEvent.WINDOW_CLOSING); List<ChildFrame> copy = new ArrayList<ChildFrame>(windows); windows.clear(); for (int i = 0; i < copy.size(); i++) { ChildFrame frame = copy.get(i); try { frame.windowClosing(true); frame.setVisible(false); WindowListener listeners[] = frame.getWindowListeners(); for (final WindowListener listener : listeners) { listener.windowClosing(event); } if (frame instanceof Closeable) { frame.close(); } frame.dispose(); } catch (Exception e) { e.printStackTrace(); } } } public static ChildFrame getFirstFrame(Class<? extends ChildFrame> frameClass) { for (int i = 0; i < windows.size(); i++) { ChildFrame frame = windows.get(i); if (frame.getClass() == frameClass) return frame; } return null; } public static List<ChildFrame> getFrames(Class<? extends ChildFrame> frameClass) { List<ChildFrame> frames = new ArrayList<ChildFrame>(); for (int i = 0; i < windows.size(); i++) { ChildFrame frame = windows.get(i); if (frame.getClass() == frameClass) frames.add(frame); } return frames; } public static void updateWindowGUIs() { for (int i = 0; i < windows.size(); i++) SwingUtilities.updateComponentTreeUI(windows.get(i)); } protected ChildFrame(String title) { this(title, false); } public ChildFrame(String title, boolean closeOnInvisible) { super(title); setIconImages(NearInfinity.getInstance().getIconImages()); this.closeOnInvisible = closeOnInvisible; windows.add(this); JPanel pane = new JPanel(); setContentPane(pane); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); pane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), pane); pane.getActionMap().put(pane, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (ChildFrame.this.closeOnInvisible) { try { if (!ChildFrame.this.windowClosing(false)) return; } catch (Exception e2) { e2.printStackTrace(); return; } windows.remove(ChildFrame.this); } ChildFrame.this.setVisible(false); } }); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (ChildFrame.this.closeOnInvisible) { try { if (!ChildFrame.this.windowClosing(false)) return; } catch (Exception e2) { throw new IllegalAccessError(); // ToDo: This is just too ugly } windows.remove(ChildFrame.this); } ChildFrame.this.setVisible(false); } } ); } public void close() { setVisible(false); windows.remove(this); } /** * This method is called whenever the dialog is about to be closed and removed from memory. * @param forced If {@code false}, the return value will be honored. * If {@code true}, the return value will be disregarded. * @return If {@code true}, the closing procedure continues. * If {@code false}, the closing procedure will be cancelled. * @throws Exception */ protected boolean windowClosing(boolean forced) throws Exception { return true; } }