1 13 14 package org.netbeans.modules.project.ui.actions; 15 16 import java.awt.Component ; 17 import java.awt.Container ; 18 import java.awt.Dimension ; 19 import java.awt.GridBagConstraints ; 20 import java.awt.GridBagLayout ; 21 import java.awt.Insets ; 22 import java.awt.event.ActionEvent ; 23 import java.awt.event.ActionListener ; 24 import java.beans.PropertyChangeEvent ; 25 import java.beans.PropertyChangeListener ; 26 import java.io.IOException ; 27 import java.util.Collection ; 28 import java.util.logging.Level ; 29 import java.util.logging.Logger ; 30 import javax.swing.AbstractAction ; 31 import javax.swing.Action ; 32 import javax.swing.BorderFactory ; 33 import javax.swing.ComboBoxModel ; 34 import javax.swing.DefaultComboBoxModel ; 35 import javax.swing.JComboBox ; 36 import javax.swing.JComponent ; 37 import javax.swing.JLabel ; 38 import javax.swing.JList ; 39 import javax.swing.JMenu ; 40 import javax.swing.JMenuItem ; 41 import javax.swing.JPanel ; 42 import javax.swing.JRadioButtonMenuItem ; 43 import javax.swing.ListCellRenderer ; 44 import javax.swing.UIManager ; 45 import javax.swing.border.Border ; 46 import javax.swing.plaf.UIResource ; 47 import org.netbeans.api.project.Project; 48 import org.netbeans.api.project.ProjectManager; 49 import org.netbeans.modules.project.ui.OpenProjectList; 50 import org.netbeans.spi.project.ProjectConfiguration; 51 import org.netbeans.spi.project.ProjectConfigurationProvider; 52 import org.openide.awt.DynamicMenuContent; 53 import org.openide.awt.Mnemonics; 54 import org.openide.util.ContextAwareAction; 55 import org.openide.util.HelpCtx; 56 import org.openide.util.Lookup; 57 import org.openide.util.Mutex; 58 import org.openide.util.MutexException; 59 import org.openide.util.NbBundle; 60 import org.openide.util.actions.CallableSystemAction; 61 import org.openide.util.actions.Presenter; 62 63 67 public class ActiveConfigAction extends CallableSystemAction implements ContextAwareAction { 68 69 private static final Logger LOGGER = Logger.getLogger(ActiveConfigAction.class.getName()); 70 71 private static final DefaultComboBoxModel EMPTY_MODEL = new DefaultComboBoxModel (); 72 private static final Object CUSTOMIZE_ENTRY = new Object (); 73 74 private final PropertyChangeListener lst; 75 private final JComboBox configListCombo; 76 private boolean listeningToCombo = true; 77 78 private Project currentProject; 79 private ProjectConfigurationProvider pcp; 80 81 public ActiveConfigAction() { 82 super(); 83 putValue("noIconInMenu", Boolean.TRUE); configListCombo = new JComboBox (); 85 configListCombo.setRenderer(new ConfigCellRenderer()); 86 configListCombo.setToolTipText(org.openide.awt.Actions.cutAmpersand(getName())); 87 configurationsListChanged(null); 88 configListCombo.addActionListener(new ActionListener () { 89 public void actionPerformed(ActionEvent e) { 90 if (!listeningToCombo) { 91 return; 92 } 93 Object o = configListCombo.getSelectedItem(); 94 if (o == CUSTOMIZE_ENTRY) { 95 activeConfigurationChanged(pcp != null ? getActiveConfiguration(pcp) : null); 96 pcp.customize(); 97 } else if (o != null) { 98 activeConfigurationSelected((ProjectConfiguration) o); 99 } 100 } 101 }); 102 lst = new PropertyChangeListener () { 103 public void propertyChange(PropertyChangeEvent evt) { 104 if (ProjectConfigurationProvider.PROP_CONFIGURATIONS.equals(evt.getPropertyName())) { 105 configurationsListChanged(getConfigurations(pcp)); 106 } else if (ProjectConfigurationProvider.PROP_CONFIGURATION_ACTIVE.equals(evt.getPropertyName())) { 107 activeConfigurationChanged(getActiveConfiguration(pcp)); 108 } 109 } 110 }; 111 activeProjectChanged(OpenProjectList.getDefault().getMainProject()); 112 OpenProjectList.getDefault().addPropertyChangeListener(new PropertyChangeListener () { 113 public void propertyChange(PropertyChangeEvent evt) { 114 if (OpenProjectList.PROPERTY_MAIN_PROJECT.equals(evt.getPropertyName())) { 115 activeProjectChanged(OpenProjectList.getDefault().getMainProject()); 116 } 117 } 118 }); 119 } 120 121 122 private synchronized void configurationsListChanged(Collection <? extends ProjectConfiguration> configs) { 123 LOGGER.log(Level.FINER, "configurationsListChanged: {0}", configs); 124 if (configs == null) { 125 configListCombo.setModel(EMPTY_MODEL); 126 configListCombo.setEnabled(false); 127 129 } else { 130 DefaultComboBoxModel model = new DefaultComboBoxModel (configs.toArray()); 131 if (pcp.hasCustomizer()) { 132 model.addElement(CUSTOMIZE_ENTRY); 133 } 134 configListCombo.setModel(model); 135 configListCombo.setEnabled(true); 136 if( null != toolbarPanel ) 137 toolbarPanel.setVisible( true ); 138 } 139 if( null != toolbarPanel && null != toolbarPanel.getParent() ) { 140 Container parentComp = toolbarPanel.getParent(); 141 parentComp.invalidate(); 142 parentComp.repaint(); 143 } 144 if (pcp != null) { 145 activeConfigurationChanged(getActiveConfiguration(pcp)); 146 } 147 } 148 149 private synchronized void activeConfigurationChanged(ProjectConfiguration config) { 150 LOGGER.log(Level.FINER, "activeConfigurationChanged: {0}", config); 151 listeningToCombo = false; 152 try { 153 configListCombo.setSelectedIndex(-1); 154 if (config != null) { 155 ComboBoxModel m = configListCombo.getModel(); 156 for (int i = 0; i < m.getSize(); i++) { 157 if (config.equals(m.getElementAt(i))) { 158 configListCombo.setSelectedIndex(i); 159 break; 160 } 161 } 162 } 163 } finally { 164 listeningToCombo = true; 165 } 166 } 167 168 private synchronized void activeConfigurationSelected(ProjectConfiguration cfg) { 169 LOGGER.log(Level.FINER, "activeConfigurationSelected: {0}", cfg); 170 if (pcp != null && cfg != null && !cfg.equals(getActiveConfiguration(pcp))) { 171 try { 172 setActiveConfiguration(pcp, cfg); 173 } catch (IOException x) { 174 LOGGER.log(Level.WARNING, null, x); 175 } 176 } 177 } 178 179 public HelpCtx getHelpCtx() { 180 return new HelpCtx(ActiveConfigAction.class); 181 } 182 183 public String getName() { 184 return NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.label"); 185 } 186 187 public void performAction() { 188 assert false; 189 } 190 191 private JPanel toolbarPanel; 192 public Component getToolbarPresenter() { 193 toolbarPanel = new JPanel (new GridBagLayout ()); 195 toolbarPanel.setOpaque(false); toolbarPanel.setMaximumSize(new Dimension (150, 80)); 197 toolbarPanel.setMinimumSize(new Dimension (150, 0)); 198 toolbarPanel.setPreferredSize(new Dimension (150, 23)); 199 toolbarPanel.add(configListCombo, new GridBagConstraints (0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets (1, 6, 1, 5), 0, 0)); 201 toolbarPanel.setEnabled( configListCombo.getItemCount() > 0 ); 203 return toolbarPanel; 204 } 205 206 class ConfigMenu extends JMenu implements DynamicMenuContent { 207 208 private final Lookup context; 209 210 public ConfigMenu(Lookup context) { 211 this.context = context; 212 if (context != null) { 213 Mnemonics.setLocalizedText(this, NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.context.label")); 214 } else { 215 Mnemonics.setLocalizedText(this, ActiveConfigAction.this.getName()); 216 } 217 } 218 219 public JComponent [] getMenuPresenters() { 220 removeAll(); 221 final ProjectConfigurationProvider<?> pcp; 222 if (context != null) { 223 Collection <? extends Project> projects = context.lookupAll(Project.class); 224 if (projects.size() == 1) { 225 pcp = projects.iterator().next().getLookup().lookup(ProjectConfigurationProvider.class); 226 } else { 227 pcp = null; 229 } 230 } else { 231 pcp = ActiveConfigAction.this.pcp; } 233 if (pcp != null) { 234 boolean something = false; 235 ProjectConfiguration activeConfig = getActiveConfiguration(pcp); 236 for (final ProjectConfiguration config : getConfigurations(pcp)) { 237 JRadioButtonMenuItem jmi = new JRadioButtonMenuItem (config.getDisplayName(), config.equals(activeConfig)); 238 jmi.addActionListener(new ActionListener () { 239 public void actionPerformed(ActionEvent e) { 240 activeConfigurationSelected(config); 241 } 242 }); 243 add(jmi); 244 something = true; 245 } 246 if (pcp.hasCustomizer()) { 247 if (something) { 248 addSeparator(); 249 } 250 something = true; 251 JMenuItem customize = new JMenuItem (); 252 Mnemonics.setLocalizedText(customize, NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.customize")); 253 customize.addActionListener(new ActionListener () { 254 public void actionPerformed(ActionEvent e) { 255 pcp.customize(); 256 } 257 }); 258 add(customize); 259 } 260 setEnabled(something); 261 } else { 262 setEnabled(false); 264 } 266 return new JComponent [] {this}; 267 } 268 269 public JComponent [] synchMenuPresenters(JComponent [] items) { 270 return getMenuPresenters(); 273 } 274 275 } 276 277 public JMenuItem getMenuPresenter() { 278 return new ConfigMenu(null); 279 } 280 281 private static class ConfigCellRenderer extends JLabel implements ListCellRenderer , UIResource { 282 283 private Border defaultBorder = getBorder(); 284 285 public ConfigCellRenderer () { 286 setOpaque(true); 287 } 288 289 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 290 setName("ComboBox.listRenderer"); 293 String label = null; 294 if (value instanceof ProjectConfiguration) { 295 label = ((ProjectConfiguration) value).getDisplayName(); 296 setBorder (defaultBorder); 297 } else if (value == CUSTOMIZE_ENTRY) { 298 label = org.openide.awt.Actions.cutAmpersand( 299 NbBundle.getMessage(ActiveConfigAction.class, "ActiveConfigAction.customize")); 300 setBorder(BorderFactory.createCompoundBorder( 301 BorderFactory.createMatteBorder(1, 0, 0, 0, 302 UIManager.getColor("controlDkShadow")), defaultBorder)); 303 } else { 304 assert value == null; 305 label = null; 306 setBorder (defaultBorder); 307 } 308 309 setText(label); 310 setIcon(null); 311 312 if ( isSelected ) { 313 setBackground(list.getSelectionBackground()); 314 setForeground(list.getSelectionForeground()); 315 } 316 else { 317 setBackground(list.getBackground()); 318 setForeground(list.getForeground()); 319 } 320 321 return this; 322 } 323 324 public String getName() { 326 String name = super.getName(); 327 return name == null ? "ComboBox.renderer" : name; } 329 330 } 331 332 private synchronized void activeProjectChanged(Project p) { 333 LOGGER.log(Level.FINER, "activeProjectChanged: {0} -> {1}", new Object [] {currentProject, p}); 334 if (currentProject != p) { 335 if (pcp != null) { 336 pcp.removePropertyChangeListener(lst); 337 } 338 currentProject = p; 339 if (currentProject != null) { 340 pcp = currentProject.getLookup().lookup(ProjectConfigurationProvider.class); 341 if (pcp != null) { 342 pcp.addPropertyChangeListener(lst); 343 } 344 } else { 345 pcp = null; 346 } 347 configurationsListChanged(pcp == null ? null : getConfigurations(pcp)); 348 349 } 350 } 351 352 public Action createContextAwareInstance(final Lookup actionContext) { 353 class A extends AbstractAction implements Presenter.Popup { 354 public void actionPerformed(ActionEvent e) { 355 assert false; 356 } 357 public JMenuItem getPopupPresenter() { 358 return new ConfigMenu(actionContext); 359 } 360 } 361 return new A(); 362 } 363 364 private static Collection <? extends ProjectConfiguration> getConfigurations(final ProjectConfigurationProvider<?> pcp) { 365 return ProjectManager.mutex().readAccess(new Mutex.Action<Collection <? extends ProjectConfiguration>>() { 366 public Collection <? extends ProjectConfiguration> run() { 367 return pcp.getConfigurations(); 368 } 369 }); 370 } 371 372 private static ProjectConfiguration getActiveConfiguration(final ProjectConfigurationProvider<?> pcp) { 373 return ProjectManager.mutex().readAccess(new Mutex.Action<ProjectConfiguration>() { 374 public ProjectConfiguration run() { 375 return pcp.getActiveConfiguration(); 376 } 377 }); 378 } 379 380 @SuppressWarnings ("unchecked") 381 private static void setActiveConfiguration(ProjectConfigurationProvider<?> pcp, final ProjectConfiguration pc) throws IOException { 382 final ProjectConfigurationProvider _pcp = pcp; 383 try { 384 ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void >() { 385 public Void run() throws IOException { 386 _pcp.setActiveConfiguration(pc); 387 return null; 388 } 389 }); 390 } catch (MutexException e) { 391 throw (IOException ) e.getException(); 392 } 393 } 394 395 } 396 | Popular Tags |