/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Contributor(s): * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun * Microsystems, Inc. All Rights Reserved. * Portions Copyright 2009 Alexander Coles (Ikonoklastik Productions). * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. */ package org.nbgit.ui.wizards; import java.awt.Component; import java.awt.Dialog; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.MalformedURLException; import java.net.URISyntaxException; import javax.swing.JButton; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.nbgit.ui.repository.GitRepositoryUI; import org.nbgit.util.GitUtils; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.NotificationLineSupport; import org.openide.WizardDescriptor; import org.openide.awt.Mnemonics; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.eclipse.jgit.transport.URIish; import static org.openide.DialogDescriptor.DEFAULT_ALIGN; import static org.openide.NotifyDescriptor.CANCEL_OPTION; import static org.openide.NotifyDescriptor.CLOSED_OPTION; public class ClonePathsWizardPanel implements WizardDescriptor.Panel { /** * The visual component that displays this panel. If you need to access the * component from this class, just use getComponent(). */ private ClonePathsPanel component; private URIish repositoryOrig; private Listener listener; private URIish pullUrl, pushUrl; private URIish defaultUrl; private String defaultUrlString; // Get the visual component for the panel. In this template, the component // is kept separate. This can be more efficient: if the wizard is created // but never displayed, or not all panels are displayed, it is better to // create only those which really need to be visible. public Component getComponent() { if (component == null) { component = new ClonePathsPanel(); initInteraction(); } return component; } private void initInteraction() { listener = new Listener(); component.defaultValuesButton.addActionListener(listener); component.changePullPathButton.addActionListener(listener); component.changePushPathButton.addActionListener(listener); } final class Listener implements ActionListener { public void actionPerformed(ActionEvent e) { URIish changedUrl; Object source = e.getSource(); if (source == component.defaultValuesButton) { setDefaultValues(); } else if (source == component.changePullPathButton) { changedUrl = changeUrl("changePullPath.Title"); //NOI18N if (changedUrl != null) { component.defaultPullPathField.setText(changedUrl.toString()); //pullUrl = (changedUrl != URIish.NO_URL) ? changedUrl : null; } } else if (source == component.changePushPathButton) { changedUrl = changeUrl("changePushPath.Title"); //NOI18N if (changedUrl != null) { component.defaultPushPathField.setText(changedUrl.toString()); //pushUrl = (changedUrl != URIish.NO_URL) ? changedUrl : null; } } else { assert false; } } } /** * Invoked when the second page of wizard <em>Clone External Repository</em> * (aka <em>Clone Other...</em>) is displayed and one of the * <em>Change...</em> buttons is pressed. It displays a repository chooser * dialog. * * @param titleMsgKey resource bundle key for the title of the repository * chooser dialog * @return {@code } of the selected repository if one was selected, * {@code HgURL.NO_URL} if the <em>Clear Path</em> button was * selected, {@code null} otherwise (button <em>Cancel</em> pressed * or the dialog closed without pressing any of the above buttons) */ private URIish changeUrl(String titleMsgKey) { int repoModeMask = GitRepositoryUI.FLAG_URL_ENABLED | GitRepositoryUI.FLAG_SHOW_HINTS; String title = getMessage(titleMsgKey); final JButton set = new JButton(); final JButton clear = new JButton(); Mnemonics.setLocalizedText(set, getMessage("changePullPushPath.Set")); //NOI18N Mnemonics.setLocalizedText(clear, getMessage("changePullPushPath.Clear")); //NOI18N final GitRepositoryUI repository = new GitRepositoryUI(repoModeMask, title, true); set.setEnabled(repository.isValid()); clear.setDefaultCapable(false); final DialogDescriptor dialogDescriptor = new DialogDescriptor( GitUtils.addContainerBorder(repository.getPanel()), title, //title true, //modal new Object[] {set, clear, CANCEL_OPTION}, set, //default option DEFAULT_ALIGN, //alignment new HelpCtx(ClonePathsWizardPanel.class.getName() + ".change"), //NOI18N null); //action listener dialogDescriptor.setClosingOptions(new Object[] {clear, CANCEL_OPTION}); final NotificationLineSupport notificationLineSupport = dialogDescriptor.createNotificationLineSupport(); class RepositoryChangeListener implements ChangeListener, ActionListener { private Dialog dialog; public void setDialog(Dialog dialog) { this.dialog = dialog; } public void stateChanged(ChangeEvent e) { assert e.getSource() == repository; boolean isValid = repository.isValid(); dialogDescriptor.setValid(isValid); set.setEnabled(isValid); if (isValid) { notificationLineSupport.clearMessages(); } else { String errMsg = repository.getMessage(); if ((errMsg != null) && (errMsg.length() != 0)) { notificationLineSupport.setErrorMessage(errMsg); } else { notificationLineSupport.clearMessages(); } } } public void actionPerformed(ActionEvent e) { if (e.getSource() != set) { return; } try { //remember the selected URL: dialogDescriptor.setValue(repository.getUrl()); /* * option "set" is not closing so we must handle closing * of the dialog explictly here: */ dialog.setVisible(false); dialog.dispose(); } catch (MalformedURLException ex) { repository.setInvalid(); notificationLineSupport.setErrorMessage(ex.getMessage()); } catch (URISyntaxException ex) { repository.setInvalid(); notificationLineSupport.setErrorMessage(ex.getMessage()); } } } RepositoryChangeListener optionListener = new RepositoryChangeListener(); repository.addChangeListener(optionListener); dialogDescriptor.setButtonListener(optionListener); Dialog dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor); optionListener.setDialog(dialog); dialog.pack(); dialog.setVisible(true); Object selectedValue = dialogDescriptor.getValue(); assert (selectedValue instanceof URIish) || (selectedValue == clear) || (selectedValue == CANCEL_OPTION) || (selectedValue == CLOSED_OPTION); if (selectedValue instanceof URIish) { return (URIish) selectedValue; } else if (selectedValue == clear) { return new URIish(); // NO_URL } else { return null; //CANCEL_OPTION, CLOSED_OPTION } } public boolean isValid() { return true; } public HelpCtx getHelp() { return new HelpCtx(ClonePathsWizardPanel.class); } public final void addChangeListener(ChangeListener l) { //always valid - no changes - no change listeners } public final void removeChangeListener(ChangeListener l) { //always valid - no changes - no change listeners } private void setDefaultValues() { setDefaultValues(true, true); } private void setDefaultValues(boolean pullPath, boolean pushPath) { if (pullPath) { component.defaultPullPathField.setText(getDefaultPath()); pullUrl = repositoryOrig; } if (pushPath) { component.defaultPushPathField.setText(getDefaultPath()); pushUrl = repositoryOrig; } } private String getDefaultPath() { if (defaultUrlString == null) { defaultUrlString = repositoryOrig.toString(); } return defaultUrlString; } // You can use a settings object to keep track of state. Normally the // settings object will be the WizardDescriptor, so you can use // WizardDescriptor.getProperty & putProperty to store information entered // by the user. public void readSettings(Object settings) { assert (settings instanceof WizardDescriptor); defaultUrl = (URIish) ((WizardDescriptor) settings).getProperty("repository"); // NOI18N URIish repository = defaultUrl; boolean repoistoryChanged = !repository.equals(repositoryOrig); repositoryOrig = repository; defaultUrlString = null; boolean resetPullPath = repoistoryChanged || (pullUrl == null); boolean resetPushPath = repoistoryChanged || (pushUrl == null); setDefaultValues(resetPullPath, resetPushPath); } public void storeSettings(Object settings) { if (settings instanceof WizardDescriptor) { ((WizardDescriptor) settings).putProperty("defaultPullPath", pullUrl); // NOI18N ((WizardDescriptor) settings).putProperty("defaultPushPath", pushUrl); // NOI18N } } private static String getMessage(String msgKey) { return NbBundle.getMessage(ClonePathsWizardPanel.class, msgKey); } }