Added
Link Here
|
1 |
/* |
2 |
* Sun Public License Notice |
3 |
* |
4 |
* The contents of this file are subject to the Sun Public License |
5 |
* Version 1.0 (the "License"). You may not use this file except in |
6 |
* compliance with the License. A copy of the License is available at |
7 |
* http://www.sun.com/ |
8 |
* |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun |
11 |
* Microsystems, Inc. All Rights Reserved. |
12 |
*/ |
13 |
|
14 |
package org.netbeans.modules.project.ui.actions; |
15 |
|
16 |
import java.awt.Component; |
17 |
import java.awt.Dimension; |
18 |
import java.awt.GridBagConstraints; |
19 |
import java.awt.GridBagLayout; |
20 |
import java.awt.Insets; |
21 |
import java.awt.event.ActionEvent; |
22 |
import java.awt.event.ActionListener; |
23 |
import java.beans.PropertyChangeEvent; |
24 |
import java.beans.PropertyChangeListener; |
25 |
import java.io.IOException; |
26 |
import java.util.Collection; |
27 |
import java.util.logging.Level; |
28 |
import java.util.logging.Logger; |
29 |
import javax.swing.AbstractAction; |
30 |
import javax.swing.Action; |
31 |
import javax.swing.ComboBoxModel; |
32 |
import javax.swing.DefaultComboBoxModel; |
33 |
import javax.swing.DefaultListCellRenderer; |
34 |
import javax.swing.JComboBox; |
35 |
import javax.swing.JComponent; |
36 |
import javax.swing.JList; |
37 |
import javax.swing.JMenu; |
38 |
import javax.swing.JMenuItem; |
39 |
import javax.swing.JPanel; |
40 |
import javax.swing.JRadioButtonMenuItem; |
41 |
import org.netbeans.api.project.Project; |
42 |
import org.netbeans.modules.project.ui.OpenProjectList; |
43 |
import org.netbeans.spi.project.ProjectConfiguration; |
44 |
import org.netbeans.spi.project.ProjectConfigurationProvider; |
45 |
import org.openide.awt.DynamicMenuContent; |
46 |
import org.openide.awt.Mnemonics; |
47 |
import org.openide.util.ContextAwareAction; |
48 |
import org.openide.util.HelpCtx; |
49 |
import org.openide.util.Lookup; |
50 |
import org.openide.util.NbBundle; |
51 |
import org.openide.util.actions.CallableSystemAction; |
52 |
import org.openide.util.actions.Presenter; |
53 |
|
54 |
/** |
55 |
* Action permitting selection of a configuration for the main project. |
56 |
* @author Greg Crawley, Adam Sotona, Jesse Glick |
57 |
*/ |
58 |
public class ActiveConfigAction extends CallableSystemAction implements ContextAwareAction { |
59 |
|
60 |
private static final DefaultComboBoxModel EMPTY_MODEL = new DefaultComboBoxModel(); |
61 |
private static final Object CUSTOMIZE_ENTRY = new Object(); |
62 |
|
63 |
private final PropertyChangeListener lst; |
64 |
private final JComboBox configListCombo; |
65 |
private boolean listeningToCombo = true; |
66 |
|
67 |
private Project currentProject; |
68 |
private ProjectConfigurationProvider cp; |
69 |
|
70 |
public ActiveConfigAction() { |
71 |
super(); |
72 |
putValue("noIconInMenu", Boolean.TRUE); // NOI18N |
73 |
configListCombo = new JComboBox(); |
74 |
configListCombo.setRenderer(new ConfigCellRenderer()); |
75 |
configListCombo.setToolTipText(org.openide.awt.Actions.cutAmpersand(getName())); |
76 |
configurationsListChanged(null); |
77 |
configListCombo.addActionListener(new ActionListener() { |
78 |
public void actionPerformed(ActionEvent e) { |
79 |
if (!listeningToCombo) { |
80 |
return; |
81 |
} |
82 |
Object o = configListCombo.getSelectedItem(); |
83 |
if (o == CUSTOMIZE_ENTRY) { |
84 |
activeConfigurationChanged(cp != null ? cp.getActiveConfiguration() : null); |
85 |
cp.customize(); |
86 |
} else if (o != null) { |
87 |
activeConfigurationSelected((ProjectConfiguration) o); |
88 |
} |
89 |
} |
90 |
}); |
91 |
lst = new PropertyChangeListener() { |
92 |
public void propertyChange(PropertyChangeEvent evt) { |
93 |
if (ProjectConfigurationProvider.PROP_CONFIGURATIONS.equals(evt.getPropertyName())) { |
94 |
configurationsListChanged(cp.getConfigurations()); |
95 |
} else if (ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE.equals(evt.getPropertyName())) { |
96 |
activeConfigurationChanged(cp.getActiveConfiguration()); |
97 |
} |
98 |
} |
99 |
}; |
100 |
activeProjectChanged(OpenProjectList.getDefault().getMainProject()); |
101 |
OpenProjectList.getDefault().addPropertyChangeListener(new PropertyChangeListener() { |
102 |
public void propertyChange(PropertyChangeEvent evt) { |
103 |
if (OpenProjectList.PROPERTY_MAIN_PROJECT.equals(evt.getPropertyName())) { |
104 |
activeProjectChanged(OpenProjectList.getDefault().getMainProject()); |
105 |
} |
106 |
} |
107 |
}); |
108 |
} |
109 |
|
110 |
|
111 |
private synchronized void configurationsListChanged(Collection<? extends ProjectConfiguration> configs) { |
112 |
if (configs == null) { |
113 |
configListCombo.setModel(EMPTY_MODEL); |
114 |
configListCombo.setEnabled(false); |
115 |
} else { |
116 |
DefaultComboBoxModel model = new DefaultComboBoxModel(configs.toArray()); |
117 |
if (cp.hasCustomizer()) { |
118 |
model.addElement(CUSTOMIZE_ENTRY); |
119 |
} |
120 |
configListCombo.setModel(model); |
121 |
configListCombo.setEnabled(true); |
122 |
} |
123 |
if (cp != null) { |
124 |
activeConfigurationChanged(cp.getActiveConfiguration()); |
125 |
} |
126 |
} |
127 |
|
128 |
private synchronized void activeConfigurationChanged(ProjectConfiguration config) { |
129 |
listeningToCombo = false; |
130 |
try { |
131 |
configListCombo.setSelectedIndex(-1); |
132 |
if (config != null) { |
133 |
ComboBoxModel m = configListCombo.getModel(); |
134 |
for (int i = 0; i < m.getSize(); i++) { |
135 |
if (config.equals(m.getElementAt(i))) { |
136 |
configListCombo.setSelectedIndex(i); |
137 |
break; |
138 |
} |
139 |
} |
140 |
} |
141 |
} finally { |
142 |
listeningToCombo = true; |
143 |
} |
144 |
} |
145 |
|
146 |
private synchronized void activeConfigurationSelected(ProjectConfiguration cfg) { |
147 |
if (cp != null && cfg != null && !cfg.equals(cp.getActiveConfiguration())) { |
148 |
try { |
149 |
cp.setActiveConfiguration(cfg); |
150 |
} catch (IOException x) { |
151 |
Logger.getLogger(ActiveConfigAction.class.getName()).log(Level.WARNING, null, x); |
152 |
} |
153 |
} |
154 |
} |
155 |
|
156 |
public HelpCtx getHelpCtx() { |
157 |
return new HelpCtx(ActiveConfigAction.class); |
158 |
} |
159 |
|
160 |
public String getName() { |
161 |
return NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.label"); |
162 |
} |
163 |
|
164 |
public void performAction() { |
165 |
assert false; |
166 |
} |
167 |
|
168 |
public Component getToolbarPresenter() { |
169 |
// Do not return combo box directly; looks bad. |
170 |
JPanel panel = new JPanel(new GridBagLayout()); |
171 |
panel.setOpaque(false); // don't interrupt JToolBar background |
172 |
panel.setMaximumSize(new Dimension(150, 80)); |
173 |
panel.setMinimumSize(new Dimension(150, 0)); |
174 |
panel.setPreferredSize(new Dimension(150, 23)); |
175 |
// XXX top inset of 2 looks better w/ small toolbar, but 1 seems to look better for large toolbar (the default): |
176 |
panel.add(configListCombo, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(1, 6, 1, 5), 0, 0)); |
177 |
return panel; |
178 |
} |
179 |
|
180 |
class ConfigMenu extends JMenu implements DynamicMenuContent { |
181 |
|
182 |
private final Lookup context; |
183 |
|
184 |
public ConfigMenu(Lookup context) { |
185 |
this.context = context; |
186 |
if (context != null) { |
187 |
Mnemonics.setLocalizedText(this, NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.context.label")); |
188 |
} else { |
189 |
Mnemonics.setLocalizedText(this, ActiveConfigAction.this.getName()); |
190 |
} |
191 |
} |
192 |
|
193 |
public JComponent[] getMenuPresenters() { |
194 |
removeAll(); |
195 |
final ProjectConfigurationProvider pcp; |
196 |
if (context != null) { |
197 |
Collection<? extends Project> projects = context.lookupAll(Project.class); |
198 |
if (projects.size() == 1) { |
199 |
pcp = projects.iterator().next().getLookup().lookup(ProjectConfigurationProvider.class); |
200 |
} else { |
201 |
// No selection, or multiselection. |
202 |
pcp = null; |
203 |
} |
204 |
} else { |
205 |
pcp = cp; // global menu item; take from main project |
206 |
} |
207 |
if (pcp != null) { |
208 |
boolean something = false; |
209 |
ProjectConfiguration activeConfig = pcp.getActiveConfiguration(); |
210 |
for (final ProjectConfiguration config : pcp.getConfigurations()) { |
211 |
JRadioButtonMenuItem jmi = new JRadioButtonMenuItem(config.getDisplayName(), config.equals(activeConfig)); |
212 |
jmi.addActionListener(new ActionListener() { |
213 |
public void actionPerformed(ActionEvent e) { |
214 |
activeConfigurationSelected(config); |
215 |
} |
216 |
}); |
217 |
add(jmi); |
218 |
something = true; |
219 |
} |
220 |
if (pcp.hasCustomizer()) { |
221 |
if (something) { |
222 |
addSeparator(); |
223 |
} |
224 |
something = true; |
225 |
JMenuItem customize = new JMenuItem(); |
226 |
Mnemonics.setLocalizedText(customize, NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.customize")); |
227 |
customize.addActionListener(new ActionListener() { |
228 |
public void actionPerformed(ActionEvent e) { |
229 |
pcp.customize(); |
230 |
} |
231 |
}); |
232 |
add(customize); |
233 |
} |
234 |
setEnabled(something); |
235 |
} else { |
236 |
// No configurations supported for this project. |
237 |
setEnabled(false); |
238 |
// to hide entirely just use: return new JComponent[0]; |
239 |
} |
240 |
return new JComponent[] {this}; |
241 |
} |
242 |
|
243 |
public JComponent[] synchMenuPresenters(JComponent[] items) { |
244 |
// Always rebuild submenu. |
245 |
// For performance, could try to reuse it if context == null and nothing has changed. |
246 |
return getMenuPresenters(); |
247 |
} |
248 |
|
249 |
} |
250 |
|
251 |
public JMenuItem getMenuPresenter() { |
252 |
return new ConfigMenu(null); |
253 |
} |
254 |
|
255 |
private static class ConfigCellRenderer extends DefaultListCellRenderer { |
256 |
|
257 |
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
258 |
if (value instanceof ProjectConfiguration) { |
259 |
return super.getListCellRendererComponent(list, ((ProjectConfiguration) value).getDisplayName(), index, isSelected, cellHasFocus); |
260 |
} else if (value == CUSTOMIZE_ENTRY) { |
261 |
String label = org.openide.awt.Actions.cutAmpersand(NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.customize")); |
262 |
return super.getListCellRendererComponent(list, label, index, isSelected, cellHasFocus); |
263 |
} else { |
264 |
assert value == null; |
265 |
return super.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); |
266 |
} |
267 |
} |
268 |
} |
269 |
|
270 |
private synchronized void activeProjectChanged(Project p) { |
271 |
if (currentProject != p) { |
272 |
if (cp != null) { |
273 |
cp.removePropertyChangeListener(lst); |
274 |
} |
275 |
currentProject = p; |
276 |
if (currentProject != null) { |
277 |
cp = currentProject.getLookup().lookup(ProjectConfigurationProvider.class); |
278 |
if (cp != null) { |
279 |
cp.addPropertyChangeListener(lst); |
280 |
} |
281 |
} else { |
282 |
cp = null; |
283 |
} |
284 |
configurationsListChanged(cp == null ? null : cp.getConfigurations()); |
285 |
|
286 |
} |
287 |
} |
288 |
|
289 |
public Action createContextAwareInstance(final Lookup actionContext) { |
290 |
class A extends AbstractAction implements Presenter.Popup { |
291 |
public void actionPerformed(ActionEvent e) { |
292 |
assert false; |
293 |
} |
294 |
public JMenuItem getPopupPresenter() { |
295 |
return new ConfigMenu(actionContext); |
296 |
} |
297 |
} |
298 |
return new A(); |
299 |
} |
300 |
|
301 |
} |