1 | // Jomic - a viewer for comic book archives. |
2 | // Copyright (C) 2004-2011 Thomas Aglassinger |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | package net.sf.jomic.ui; |
17 | |
18 | import java.awt.event.ActionEvent; |
19 | import java.awt.event.ActionListener; |
20 | import java.io.File; |
21 | import java.util.ArrayList; |
22 | import java.util.Iterator; |
23 | import java.util.List; |
24 | |
25 | import javax.swing.JMenu; |
26 | import javax.swing.JMenuItem; |
27 | |
28 | import net.sf.jomic.tools.ActionDelegate; |
29 | import net.sf.jomic.tools.LocaleTools; |
30 | |
31 | import org.apache.commons.logging.Log; |
32 | import org.apache.commons.logging.LogFactory; |
33 | |
34 | /** |
35 | * Menu to collect files recently opened. |
36 | * |
37 | * @author Thomas Aglassinger |
38 | */ |
39 | public class OpenRecentMenu extends JMenu |
40 | { |
41 | private static final String OPEN_RECENT = "openRecent"; |
42 | |
43 | private JMenuItem clearRecentFilesItem; |
44 | private ActionDelegate delegate; |
45 | private boolean hasFiles; |
46 | private LocaleTools localeTools; |
47 | private Log logger; |
48 | private List menuItems; |
49 | |
50 | OpenRecentMenu(ActionDelegate newDelegate) { |
51 | super("Open recent"); |
52 | assert newDelegate != null; |
53 | logger = LogFactory.getLog(OpenRecentMenu.class); |
54 | localeTools = LocaleTools.instance(); |
55 | delegate = newDelegate; |
56 | menuItems = new ArrayList(); |
57 | setText(localeTools.getMenuItemLabel(LocaleTools.MENU_FILE, OPEN_RECENT)); |
58 | clearRecentFilesItem = localeTools.createMenuItem(LocaleTools.MENU_FILE, OPEN_RECENT + ".clearMenu"); |
59 | clearRecentFilesItem.setActionCommand(Commands.CLEAR_RECENT); |
60 | clearRecentFilesItem.addActionListener( |
61 | new ClearOpenRecentMenuListener()); |
62 | setEnabled(false); |
63 | } |
64 | |
65 | /** |
66 | * Enable the menu, unless there are no files, in which case it is disabled. |
67 | */ |
68 | void setEnabledUnlessEmpty() { |
69 | if (logger.isDebugEnabled()) { |
70 | logger.debug("setEnabledUnlessEmpty: " + hasFiles); |
71 | } |
72 | setEnabled(hasFiles); |
73 | } |
74 | |
75 | public void dispose() { |
76 | removeAllMenuItems(); |
77 | } |
78 | |
79 | void updateMenuItems(final List files) { |
80 | assert files != null; |
81 | File[] fileArray = (File[]) files.toArray(new File[0]); |
82 | |
83 | removeAllMenuItems(); |
84 | |
85 | int fileCount = fileArray.length; |
86 | |
87 | for (int i = 0; i < fileCount; i += 1) { |
88 | File file = fileArray[i]; |
89 | JMenuItem newMenuItem = new JMenuItem(file.getName()); |
90 | |
91 | menuItems.add(newMenuItem); |
92 | |
93 | ActionListener listener = new OpenRecentFileActionListener(delegate, file); |
94 | |
95 | newMenuItem.setActionCommand(Commands.OPEN_RECENT); |
96 | newMenuItem.addActionListener(listener); |
97 | add(newMenuItem); |
98 | } |
99 | hasFiles = fileCount > 0; |
100 | if (hasFiles) { |
101 | addSeparator(); |
102 | add(clearRecentFilesItem); |
103 | setEnabled(true); |
104 | } else { |
105 | if (logger.isDebugEnabled()) { |
106 | logger.debug("disabled because there are no files"); |
107 | } |
108 | setEnabled(false); |
109 | } |
110 | } |
111 | |
112 | private void removeAllMenuItems() { |
113 | Iterator rider = menuItems.iterator(); |
114 | |
115 | while (rider.hasNext()) { |
116 | JMenuItem oldMenuItem = (JMenuItem) rider.next(); |
117 | ActionListener[] oldListeners = oldMenuItem.getActionListeners(); |
118 | int oldListenersCount = oldListeners.length; |
119 | |
120 | if (oldListenersCount > 0) { |
121 | assert oldListenersCount |
122 | == 1 : "menu item must have 0 or 1 ActionListener, but has " + oldListenersCount; |
123 | oldMenuItem.removeActionListener(oldListeners[0]); |
124 | } else { |
125 | logger.warn("oldListenerCount = 0; OutOfMemoryError during menu setup?"); |
126 | } |
127 | } |
128 | menuItems.clear(); |
129 | removeAll(); |
130 | hasFiles = false; |
131 | } |
132 | |
133 | /** |
134 | * Listener to clear recent files menu. |
135 | * |
136 | * @author Thomas Aglassinger |
137 | */ |
138 | private final class ClearOpenRecentMenuListener implements ActionListener |
139 | { |
140 | private ClearOpenRecentMenuListener() { |
141 | // Do nothing. |
142 | super(); |
143 | } |
144 | |
145 | public void actionPerformed(final ActionEvent event) { |
146 | assert event.getSource() == clearRecentFilesItem; |
147 | assert event.getActionCommand() != null; |
148 | assert event.getActionCommand().equals(Commands.CLEAR_RECENT); |
149 | removeAllMenuItems(); |
150 | setEnabled(false); |
151 | delegate.actionPerformed(event); |
152 | } |
153 | } |
154 | } |