001package jmri.util;
002
003import java.awt.Frame;
004import java.awt.event.ActionEvent;
005import java.util.ArrayList;
006import java.util.List;
007import javax.swing.AbstractAction;
008import javax.swing.JCheckBoxMenuItem;
009import javax.swing.JMenu;
010import javax.swing.JMenuItem;
011import javax.swing.JSeparator;
012import javax.swing.event.MenuEvent;
013import jmri.util.swing.WindowInterface;
014
015/**
016 * Creates a menu showing all open windows and allows to bring one in front
017 *
018 * @author Giorgio Terdina Copyright 2008
019 */
020public class WindowMenu extends JMenu implements javax.swing.event.MenuListener {
021
022    private Frame parentFrame; // Keep note of the window containing the menu
023    
024    private List<JmriJFrame> framesList; // Keep the list of windows, in order to find out which window was selected
025
026    private static List<String> ignoredFrames = new ArrayList<String>();  // list of frames to not display
027    
028    public WindowMenu(WindowInterface wi) {
029        super(Bundle.getMessage("MenuWindow"));
030        parentFrame = wi.getFrame();
031        addMenuListener(this);
032    }
033
034    /**
035     * Provide a list of JmriJFrame titles that will -not- appear
036     * in the Windows menu.  Those frames may or may not remain visible,
037     * but they won't be selectable from the menu.
038     */
039    public static void setIgnoredFrames(List<String> frames) {
040        ignoredFrames = new ArrayList<>(frames);
041    }
042    
043    public static List<String> getIgnoredFrames() {
044        return new ArrayList<>(ignoredFrames);
045    }
046    
047    @Override
048    public void menuSelected(MenuEvent e) {
049        String windowName;
050        List<JmriJFrame> tempList = JmriJFrame.getFrameList();
051        removeAll();
052        
053        add(new AbstractAction(Bundle.getMessage("ButtonClose")) {
054            @Override
055            public void actionPerformed(ActionEvent e) {
056                if (parentFrame != null) {
057                    parentFrame.dispatchEvent(
058                              new java.awt.event.WindowEvent(parentFrame, 
059                                        java.awt.event.WindowEvent.WINDOW_CLOSING));
060                 }
061            }    
062        });
063        add(new AbstractAction(Bundle.getMessage("MenuItemMinimize")) {
064            @Override
065            public void actionPerformed(ActionEvent e) {
066                // the next line works on Java 2, but not 1.1.8
067                if (parentFrame != null) {
068                    parentFrame.setState(Frame.ICONIFIED);
069                }
070            }
071        });
072        add(new JSeparator());
073
074        framesList = new ArrayList<>();
075        
076        int framesNumber = tempList.size();
077        for (int i = 0; i < framesNumber; i++) {
078            JmriJFrame iFrame = tempList.get(i);
079            windowName = iFrame.getTitle();
080            
081            if (windowName.equals("")) {
082                windowName = "Untitled";
083            }
084            
085            if (ignoredFrames.contains(windowName)) {
086                continue;
087            }
088            
089            framesList.add(iFrame);
090            
091            JCheckBoxMenuItem newItem = new JCheckBoxMenuItem(new AbstractAction(windowName) {
092                @Override
093                public void actionPerformed(ActionEvent e) {
094                    JMenuItem selectedItem = (JMenuItem) e.getSource();
095                    // Since different windows can have the same name, look for the position of the selected menu item
096                    int itemCount = getItemCount();
097                    // Skip possible other items at the top of the menu (for example, "Minimize")
098                    int firstItem = itemCount - framesList.size();
099                    for (int i = firstItem; i < itemCount; i++) {
100                        if (selectedItem == getItem(i)) {
101                            i -= firstItem;
102                            // Retrieve the corresponding window
103                            if (i < framesList.size()) { // "i" should always be < framesList.size(), but it's better to make sure
104                                framesList.get(i).setVisible(true);
105                                framesList.get(i).setExtendedState(Frame.NORMAL);
106                                return;
107                            }
108                        }
109                    }
110                }
111            });
112            if (iFrame == parentFrame) {
113                newItem.setState(true);
114            }
115            add(newItem);
116        }
117    }
118
119    @Override
120    public void menuDeselected(MenuEvent e) {
121    }
122
123    @Override
124    public void menuCanceled(MenuEvent e) {
125    }
126
127}