001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.mercurial.ui.repository;
043:
044: import java.awt.BorderLayout;
045: import java.awt.Component;
046: import java.awt.Dialog;
047: import java.awt.Dimension;
048: import java.awt.event.ActionEvent;
049: import java.awt.event.ActionListener;
050: import java.awt.event.FocusEvent;
051: import java.awt.event.FocusListener;
052: import java.awt.event.ItemEvent;
053: import java.awt.event.ItemListener;
054: import java.beans.PropertyChangeEvent;
055: import java.beans.PropertyChangeListener;
056: import java.lang.reflect.InvocationTargetException;
057: import java.net.MalformedURLException;
058: import java.text.MessageFormat;
059: import java.util.ArrayList;
060: import java.util.Iterator;
061: import java.util.LinkedHashSet;
062: import java.util.List;
063: import java.util.Set;
064: import java.util.Vector;
065: import javax.swing.BorderFactory;
066: import javax.swing.ComboBoxModel;
067: import javax.swing.DefaultComboBoxModel;
068: import javax.swing.JPanel;
069: import javax.swing.SwingUtilities;
070: import javax.swing.event.DocumentEvent;
071: import javax.swing.event.DocumentListener;
072: import javax.swing.text.JTextComponent;
073: import org.netbeans.api.options.OptionsDisplayer;
074: import org.netbeans.modules.mercurial.HgModuleConfig;
075: import org.netbeans.modules.versioning.util.DialogBoundsPreserver;
076: import org.openide.DialogDescriptor;
077: import org.openide.DialogDisplayer;
078: import org.openide.ErrorManager;
079: import org.openide.util.HelpCtx;
080: import org.openide.util.NbBundle;
081:
082: /**
083: * @author Tomas Stupka
084: */
085: public class Repository implements ActionListener, DocumentListener,
086: FocusListener, ItemListener {
087:
088: public final static int FLAG_URL_EDITABLE = 2;
089: public final static int FLAG_URL_ENABLED = 4;
090: public final static int FLAG_ACCEPT_REVISION = 8;
091: public final static int FLAG_SHOW_REMOVE = 16;
092: public final static int FLAG_SHOW_HINTS = 32;
093: public final static int FLAG_SHOW_PROXY = 64;
094:
095: private final static String LOCAL_URL_HELP = "file:///repository_path"; // NOI18N
096: private final static String HTTP_URL_HELP = "http://[username[:password]@]hostname/repository_path"; // NOI18N
097: private final static String HTTPS_URL_HELP = "https://[username[:password]@]hostname/repository_path"; // NOI18N
098: private final static String STATIC_HTTP_URL_HELP = "static-http://hostname/repository_path"; // NOI18N
099: private final static String SSH_URL_HELP = "ssh://hostname/repository_path"; // NOI18N
100:
101: private RepositoryPanel repositoryPanel;
102: private boolean valid = true;
103: private List<PropertyChangeListener> listeners;
104:
105: private RepositoryConnection editedRC;
106:
107: public static final String PROP_VALID = "valid"; // NOI18N
108:
109: private String message;
110: private int modeMask;
111: private Dimension maxNeededSize;
112: private boolean bPushPull;
113: private static int HG_PUSH_PULL_VERT_PADDING = 30;
114:
115: public Repository(String titleLabel) {
116: this (0, titleLabel, false);
117: }
118:
119: public Repository(int modeMask, String titleLabel, boolean bPushPull) {
120:
121: this .modeMask = modeMask;
122:
123: initPanel();
124:
125: repositoryPanel.titleLabel.setText(titleLabel);
126:
127: repositoryPanel.urlComboBox
128: .setEditable(isSet(FLAG_URL_EDITABLE));
129: repositoryPanel.urlComboBox.setEnabled(isSet(FLAG_URL_ENABLED));
130: repositoryPanel.tunnelHelpLabel
131: .setVisible(isSet(FLAG_SHOW_HINTS));
132: repositoryPanel.tipLabel.setVisible(isSet(FLAG_SHOW_HINTS));
133: repositoryPanel.removeButton
134: .setVisible(isSet(FLAG_SHOW_REMOVE));
135:
136: //repositoryPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 0));
137:
138: // retrieve the dialog size for the largest configuration
139: if (bPushPull)
140: updateVisibility("foo:"); // NOI18N
141: else
142: updateVisibility("https:"); // NOI18N
143: maxNeededSize = repositoryPanel.getPreferredSize();
144:
145: repositoryPanel.savePasswordCheckBox.setSelected(HgModuleConfig
146: .getDefault().getSavePassword());
147: refreshUrlHistory();
148: }
149:
150: //public void selectUrl(SVNUrl url, boolean force) {
151: // DefaultComboBoxModel dcbm = (DefaultComboBoxModel) repositoryPanel.urlComboBox.getModel();
152: // int idx = dcbm.getIndexOf(url.toString());
153: // if(idx > -1) {
154: // dcbm.setSelectedItem(url.toString());
155: // } else if(force) {
156: // RepositoryConnection rc = new RepositoryConnection(url.toString());
157: // dcbm.addElement(rc);
158: // dcbm.setSelectedItem(rc);
159: // }
160: //}
161:
162: public void actionPerformed(ActionEvent e) {
163: if (e.getSource() == repositoryPanel.proxySettingsButton) {
164: onProxyConfiguration();
165: } else if (e.getSource() == repositoryPanel.removeButton) {
166: onRemoveClick();
167: } else if (e.getSource() == repositoryPanel.savePasswordCheckBox) {
168: onSavePasswordChange();
169: }
170: }
171:
172: private void onProxyConfiguration() {
173: OptionsDisplayer.getDefault().open("General"); // NOI18N
174: }
175:
176: private void initPanel() {
177: repositoryPanel = new RepositoryPanel();
178:
179: repositoryPanel.proxySettingsButton.addActionListener(this );
180: repositoryPanel.removeButton.addActionListener(this );
181:
182: repositoryPanel.urlComboBox.addActionListener(this );
183: getUrlComboEditor().getDocument().addDocumentListener(this );
184:
185: repositoryPanel.userPasswordField.getDocument()
186: .addDocumentListener(this );
187: repositoryPanel.userPasswordField.addFocusListener(this );
188:
189: repositoryPanel.userTextField.getDocument()
190: .addDocumentListener(this );
191: repositoryPanel.tunnelCommandTextField.getDocument()
192: .addDocumentListener(this );
193: repositoryPanel.savePasswordCheckBox.addActionListener(this );
194:
195: repositoryPanel.urlComboBox.addItemListener(this );
196:
197: onSelectedRepositoryChange();
198: }
199:
200: public void refreshUrlHistory() {
201:
202: List<RepositoryConnection> recentUrls = HgModuleConfig
203: .getDefault().getRecentUrls();
204:
205: Set<RepositoryConnection> recentRoots = new LinkedHashSet<RepositoryConnection>();
206: recentRoots.addAll(recentUrls);
207:
208: if (repositoryPanel.urlComboBox.isEditable()) {
209: // templates for supported connection methods
210: recentRoots.add(new RepositoryConnection("file:///")); // NOI18N
211: recentRoots.add(new RepositoryConnection("http://")); // NOI18N
212: recentRoots.add(new RepositoryConnection("https://")); // NOI18N
213: recentRoots.add(new RepositoryConnection("static-http://")); // NOI18N
214: recentRoots.add(new RepositoryConnection("ssh://")); // NOI18N
215: }
216: ;
217:
218: ComboBoxModel rootsModel = new RepositoryModel(
219: new Vector<RepositoryConnection>(recentRoots));
220: repositoryPanel.urlComboBox.setModel(rootsModel);
221:
222: if (recentRoots.size() > 0) {
223: repositoryPanel.urlComboBox.setSelectedIndex(0);
224: refresh(getSelectedRC());
225: }
226:
227: if (repositoryPanel.urlComboBox.isEditable()) {
228: JTextComponent textEditor = getUrlComboEditor();
229: textEditor.selectAll();
230: }
231: updateVisibility();
232: }
233:
234: public void storeRecentUrls() {
235: HgModuleConfig.getDefault().setRecentUrls(getRecentUrls());
236: }
237:
238: private List<RepositoryConnection> getRecentUrls() {
239: ComboBoxModel model = repositoryPanel.urlComboBox.getModel();
240: List<RepositoryConnection> ret = new ArrayList<RepositoryConnection>(
241: model.getSize());
242: for (int i = 0; i < model.getSize(); i++) {
243: ret.add((RepositoryConnection) model.getElementAt(i));
244: }
245: return ret;
246: }
247:
248: private JTextComponent getUrlComboEditor() {
249: Component editor = repositoryPanel.urlComboBox.getEditor()
250: .getEditorComponent();
251: JTextComponent textEditor = (JTextComponent) editor;
252: return textEditor;
253: }
254:
255: public void setEditable(boolean editable) {
256: repositoryPanel.urlComboBox.setEditable(editable);
257: repositoryPanel.userPasswordField.setEditable(editable);
258: repositoryPanel.userTextField.setEditable(editable);
259: repositoryPanel.proxySettingsButton.setEnabled(editable);
260: //repositoryPanel.savePasswordCheckBox.setEnabled(editable);
261: }
262:
263: public void storeConfigValues() {
264: RepositoryConnection rc = getSelectedRC();
265: if (rc == null) {
266: return; // uups
267: }
268:
269: //try {
270: //SVNUrl repositoryUrl = rc.getSvnUrl();
271: //if(repositoryUrl.getProtocol().startsWith("svn+")) { // NOI18N
272: // SvnConfigFiles.getInstance().setExternalCommand(getTunnelName(repositoryUrl.getProtocol()), repositoryPanel.tunnelCommandTextField.getText());
273: //}
274: //} catch (MalformedURLException mue) {
275: // should not happen
276: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, mue);
277: //}
278:
279: }
280:
281: public void insertUpdate(DocumentEvent e) {
282: textChanged(e);
283: }
284:
285: public void removeUpdate(DocumentEvent e) {
286: textChanged(e);
287: }
288:
289: public void changedUpdate(DocumentEvent e) {
290: textChanged(e);
291: }
292:
293: private void textChanged(final DocumentEvent e) {
294: // repost later to AWT otherwise it can deadlock because
295: // the document is locked while firing event and we try
296: // synchronously access its content from selected repository
297: Runnable awt = new Runnable() {
298: public void run() {
299: if (e.getDocument() == repositoryPanel.userTextField
300: .getDocument()) {
301: onUsernameChange();
302: } else if (e.getDocument() == repositoryPanel.userPasswordField
303: .getDocument()) {
304: onPasswordChange();
305: } else if (e.getDocument() == ((JTextComponent) repositoryPanel.urlComboBox
306: .getEditor().getEditorComponent())
307: .getDocument()) {
308: onSelectedRepositoryChange();
309: } else if (e.getDocument() == (repositoryPanel.tunnelCommandTextField
310: .getDocument())) {
311: onTunnelCommandChange();
312: }
313: validateHgUrl();
314: }
315: };
316: SwingUtilities.invokeLater(awt);
317: }
318:
319: /**
320: * Fast url syntax check. It can invalidate the whole step
321: */
322: private void validateHgUrl() {
323: boolean valid = true;
324:
325: RepositoryConnection rc = null;
326: try {
327: rc = getSelectedRC();
328: // check for a valid svnurl
329: rc.getHgUrl();
330: //if(!isSet(FLAG_ACCEPT_REVISION) && !rc.getSvnRevision().equals(SVNRevision.HEAD))
331: //{
332: // message = NbBundle.getMessage(Repository.class, "MSG_Repository_OnlyHEADRevision"); // NOI18N
333: // valid = false;
334: //} else {
335: // // check for a valid svnrevision
336: // rc.getSvnRevision();
337: //}
338: } catch (Exception ex) {
339: message = ex.getLocalizedMessage();
340: valid = false;
341: }
342:
343: if (valid) {
344: valid = rc != null && !rc.getUrl().equals(""); // NOI18N
345: //if(rc.getUrl().startsWith("svn+") && repositoryPanel.tunnelCommandTextField.getText().trim().equals("")) { // NOI18N
346: // valid = false;
347: //}
348: }
349:
350: setValid(valid, message);
351: repositoryPanel.proxySettingsButton.setEnabled(valid);
352: repositoryPanel.userPasswordField.setEnabled(valid);
353: repositoryPanel.userTextField.setEnabled(valid);
354: //repositoryPanel.savePasswordCheckBox.setEnabled(valid);
355:
356: repositoryPanel.removeButton.setEnabled(rc != null
357: && rc.getUrl().length() > 0);
358: }
359:
360: /**
361: * Always updates UI fields visibility.
362: */
363: private void onSelectedRepositoryChange() {
364: setValid(true, ""); // NOI18N
365: String urlString = ""; // NOI18N
366: try {
367: urlString = getUrlString();
368: } catch (InterruptedException ex) {
369: return; // should not happen
370: }
371:
372: if (urlString != null) {
373:
374: RepositoryConnection editedrc = getEditedRC();
375: editedrc.setUrl(urlString);
376:
377: DefaultComboBoxModel dcbm = (DefaultComboBoxModel) repositoryPanel.urlComboBox
378: .getModel();
379: int idx = dcbm.getIndexOf(editedrc);
380: if (idx > -1) {
381: //dcbm.setSelectedItem(urlString);
382: refresh((RepositoryConnection) dcbm.getElementAt(idx));
383: }
384: if (urlString.startsWith("svn+")) { // NOI18N
385: String tunnelName = getTunnelName(urlString).trim();
386: if (repositoryPanel.tunnelCommandTextField.getText()
387: .trim().equals("")
388: && // NOI18N
389: tunnelName != null && !tunnelName.equals("")) // NOI18N
390: {
391: //repositoryPanel.tunnelCommandTextField.setText(SvnConfigFiles.getInstance().getExternalCommand(tunnelName));
392: }
393: }
394:
395: editedrc.setUsername(repositoryPanel.userTextField
396: .getText());
397: editedrc.setPassword(new String(
398: repositoryPanel.userPasswordField.getPassword()));
399: editedrc
400: .setExternalCommand(repositoryPanel.tunnelCommandTextField
401: .getText());
402: editedrc
403: .setSavePassword(repositoryPanel.savePasswordCheckBox
404: .isSelected());
405: }
406: message = ""; // NOI18N
407: updateVisibility();
408: }
409:
410: private RepositoryConnection getEditedRC() {
411: if (editedRC == null) {
412: editedRC = new RepositoryConnection(""); // NOI18N
413: }
414: return editedRC;
415: }
416:
417: private void updateVisibility() {
418: try {
419: updateVisibility(getUrlString());
420: } catch (InterruptedException ex) {
421: return;
422: }
423: }
424:
425: /** Shows proper fields depending on Mercurial connection method. */
426: private void updateVisibility(String selectedUrlString) {
427:
428: boolean authFields = false;
429: boolean proxyFields = false;
430: boolean sshFields = false;
431: if (selectedUrlString.startsWith("http:")) { // NOI18N
432: repositoryPanel.tipLabel.setText(HTTP_URL_HELP);
433: authFields = true;
434: proxyFields = true;
435: } else if (selectedUrlString.startsWith("https:")) { // NOI18N
436: repositoryPanel.tipLabel.setText(HTTPS_URL_HELP);
437: //authFields = true;
438: proxyFields = true;
439: } else if (selectedUrlString.startsWith("static-http:")) { // NOI18N
440: repositoryPanel.tipLabel.setText(STATIC_HTTP_URL_HELP);
441: authFields = true;
442: proxyFields = true;
443: } else if (selectedUrlString.startsWith("ssh")) { // NOI18N
444: repositoryPanel.tipLabel
445: .setText(getSVNTunnelTip(selectedUrlString));
446: sshFields = true;
447: } else if (selectedUrlString.startsWith("file:")) { // NOI18N
448: repositoryPanel.tipLabel.setText(LOCAL_URL_HELP);
449: } else {
450: repositoryPanel.tipLabel.setText(NbBundle.getMessage(
451: Repository.class, "MSG_Repository_Url_Help",
452: new Object[] { // NOI18N
453: LOCAL_URL_HELP, HTTP_URL_HELP, HTTPS_URL_HELP,
454: STATIC_HTTP_URL_HELP, SSH_URL_HELP
455: //LOCAL_URL_HELP, HTTP_URL_HELP, STATIC_HTTP_URL_HELP, SSH_URL_HELP
456: }));
457: }
458:
459: //repositoryPanel.userPasswordField.setVisible(authFields);
460: //repositoryPanel.passwordLabel.setVisible(authFields);
461: //repositoryPanel.userTextField.setVisible(authFields);
462: //repositoryPanel.leaveBlankLabel.setVisible(authFields);
463: //repositoryPanel.userLabel.setVisible(authFields);
464: //repositoryPanel.savePasswordCheckBox.setVisible(authFields);
465: repositoryPanel.userPasswordField.setVisible(false);
466: repositoryPanel.passwordLabel.setVisible(false);
467: repositoryPanel.userTextField.setVisible(false);
468: repositoryPanel.leaveBlankLabel.setVisible(false);
469: repositoryPanel.userLabel.setVisible(false);
470: repositoryPanel.savePasswordCheckBox.setVisible(false);
471: repositoryPanel.proxySettingsButton.setVisible(proxyFields
472: && ((modeMask & FLAG_SHOW_PROXY) != 0));
473: //repositoryPanel.tunnelCommandTextField.setVisible(sshFields);
474: //repositoryPanel.tunnelCommandLabel.setVisible(sshFields);
475: //repositoryPanel.tunnelLabel.setVisible(sshFields);
476: //repositoryPanel.tunnelHelpLabel.setVisible(sshFields);
477: repositoryPanel.savePasswordCheckBox.setVisible(false);
478: repositoryPanel.tunnelCommandTextField.setVisible(false);
479: repositoryPanel.tunnelCommandLabel.setVisible(false);
480: repositoryPanel.tunnelLabel.setVisible(false);
481: repositoryPanel.tunnelHelpLabel.setVisible(false);
482: }
483:
484: private String getSVNTunnelTip(String urlString) {
485: //String tunnelName = getTunnelName(urlString);
486: //return MessageFormat.format(SSH_URL_HELP, tunnelName).trim();
487: return SSH_URL_HELP;
488: }
489:
490: private String getTunnelName(String urlString) {
491: int idx = urlString.indexOf(":", 4); // NOI18N
492: if (idx < 0) {
493: idx = urlString.length();
494: }
495: return urlString.substring(4, idx);
496: }
497:
498: /**
499: * Load selected root from Swing structures (from arbitrary thread).
500: * @return null on failure
501: */
502: private String getUrlString() throws InterruptedException {
503: if (!repositoryPanel.urlComboBox.isEditable()) {
504: Object selection = repositoryPanel.urlComboBox
505: .getSelectedItem();
506: if (selection != null) {
507: return selection.toString().trim();
508: }
509: return ""; // NOI18N
510: } else {
511: final String[] hgUrl = new String[1];
512: try {
513: Runnable awt = new Runnable() {
514: public void run() {
515: hgUrl[0] = (String) repositoryPanel.urlComboBox
516: .getEditor().getItem().toString()
517: .trim();
518: }
519: };
520: if (SwingUtilities.isEventDispatchThread()) {
521: awt.run();
522: } else {
523: SwingUtilities.invokeAndWait(awt);
524: }
525: return hgUrl[0].trim();
526: } catch (InvocationTargetException e) {
527: ErrorManager err = ErrorManager.getDefault();
528: err.notify(e);
529: }
530: return null;
531: }
532: }
533:
534: public RepositoryConnection getSelectedRC() {
535: String urlString;
536: try {
537: urlString = getUrlString();
538: } catch (InterruptedException ex) {
539: // should not happen
540: ErrorManager.getDefault().notify(ex);
541: return null;
542: }
543: ;
544:
545: DefaultComboBoxModel dcbm = (DefaultComboBoxModel) repositoryPanel.urlComboBox
546: .getModel();
547: int idx = dcbm.getIndexOf(urlString);
548:
549: if (idx > -1) {
550: return (RepositoryConnection) dcbm.getElementAt(idx);
551: }
552: return getEditedRC();
553: }
554:
555: public boolean savePassword() {
556: return repositoryPanel.savePasswordCheckBox.isSelected();
557: }
558:
559: private void onUsernameChange() {
560: RepositoryConnection rc = getSelectedRC();
561: if (rc != null) {
562: rc.setUsername(repositoryPanel.userTextField.getText());
563: }
564: setValid(true, ""); // NOI18N
565: }
566:
567: private void onPasswordChange() {
568: RepositoryConnection rc = getSelectedRC();
569: if (rc != null) {
570: rc.setPassword(new String(repositoryPanel.userPasswordField
571: .getPassword()));
572: }
573: setValid(true, ""); // NOI18N
574: }
575:
576: private void onTunnelCommandChange() {
577: RepositoryConnection rc = getSelectedRC();
578: if (rc != null) {
579: rc
580: .setExternalCommand(repositoryPanel.tunnelCommandTextField
581: .getText());
582: }
583: }
584:
585: private void onRemoveClick() {
586: RepositoryConnection rc = getSelectedRC();
587: if (rc != null) {
588: remove(rc);
589: }
590: }
591:
592: private void onSavePasswordChange() {
593: Runnable awt = new Runnable() {
594: public void run() {
595: RepositoryConnection rc = getSelectedRC();
596: if (rc != null) {
597: rc
598: .setSavePassword(repositoryPanel.savePasswordCheckBox
599: .isSelected());
600: }
601: validateHgUrl();
602: }
603: };
604: SwingUtilities.invokeLater(awt);
605: }
606:
607: public RepositoryPanel getPanel() {
608: return repositoryPanel;
609: }
610:
611: public boolean isValid() {
612: return valid;
613: }
614:
615: private void setValid(boolean valid, String message) {
616: boolean oldValue = this .valid;
617: this .message = message;
618: this .valid = valid;
619: fireValidPropertyChanged(oldValue, valid);
620: }
621:
622: private void fireValidPropertyChanged(boolean oldValue,
623: boolean valid) {
624: if (listeners == null) {
625: return;
626: }
627: for (Iterator it = listeners.iterator(); it.hasNext();) {
628: PropertyChangeListener l = (PropertyChangeListener) it
629: .next();
630: l.propertyChange(new PropertyChangeEvent(this , PROP_VALID,
631: new Boolean(oldValue), new Boolean(valid)));
632: }
633: }
634:
635: public void addPropertyChangeListener(PropertyChangeListener l) {
636: if (listeners == null) {
637: listeners = new ArrayList<PropertyChangeListener>();
638: }
639: listeners.add(l);
640: }
641:
642: public void removePropertyChangeListener(PropertyChangeListener l) {
643: if (listeners == null) {
644: return;
645: }
646: listeners.remove(l);
647: }
648:
649: public String getMessage() {
650: return message;
651: }
652:
653: public void focusGained(FocusEvent focusEvent) {
654: if (focusEvent.getSource() == repositoryPanel.userPasswordField) {
655: repositoryPanel.userPasswordField.selectAll();
656: }
657: }
658:
659: public void focusLost(FocusEvent focusEvent) {
660: // do nothing
661: }
662:
663: public void remove(RepositoryConnection toRemove) {
664: RepositoryModel model = (RepositoryModel) repositoryPanel.urlComboBox
665: .getModel();
666: model.removeElement(toRemove);
667: }
668:
669: public void itemStateChanged(ItemEvent evt) {
670: if (evt.getStateChange() == ItemEvent.SELECTED) {
671: RepositoryConnection rc = (RepositoryConnection) evt
672: .getItem();
673: refresh(rc);
674: updateVisibility();
675: editedRC = new RepositoryConnection(rc);
676: } else if (evt.getStateChange() == ItemEvent.DESELECTED) {
677: updateVisibility();
678: }
679: }
680:
681: private void refresh(RepositoryConnection rc) {
682: repositoryPanel.userTextField.setText(rc.getUsername());
683: repositoryPanel.userPasswordField.setText(rc.getPassword());
684: repositoryPanel.tunnelCommandTextField.setText(rc
685: .getExternalCommand());
686: repositoryPanel.savePasswordCheckBox.setSelected(rc
687: .getSavePassword());
688: }
689:
690: public void setTipVisible(Boolean flag) {
691: repositoryPanel.tipLabel.setVisible(flag);
692: }
693:
694: public boolean show(String title, HelpCtx helpCtx,
695: boolean setMaxNeddedSize) {
696: RepositoryDialogPanel corectPanel = new RepositoryDialogPanel();
697: corectPanel.panel.setLayout(new BorderLayout());
698: JPanel p = getPanel();
699: if (setMaxNeddedSize) {
700: if (bPushPull) {
701: maxNeededSize.setSize(maxNeededSize.width,
702: maxNeededSize.height
703: + HG_PUSH_PULL_VERT_PADDING);
704: }
705: p.setPreferredSize(maxNeededSize);
706: }
707: corectPanel.panel.add(p, BorderLayout.NORTH);
708: DialogDescriptor dialogDescriptor = new DialogDescriptor(
709: corectPanel, title); // NOI18N
710: showDialog(dialogDescriptor, helpCtx, null);
711: return dialogDescriptor.getValue() == DialogDescriptor.OK_OPTION;
712: }
713:
714: public Object show(String title, HelpCtx helpCtx, Object[] options,
715: boolean setMaxNeededSize, String name) {
716: RepositoryDialogPanel corectPanel = new RepositoryDialogPanel();
717: corectPanel.panel.setLayout(new BorderLayout());
718: corectPanel.panel.add(getPanel(), BorderLayout.NORTH);
719: DialogDescriptor dialogDescriptor = new DialogDescriptor(
720: corectPanel, title); // NOI18N
721: JPanel p = getPanel();
722: if (setMaxNeededSize) {
723: if (bPushPull) {
724: maxNeededSize.setSize(maxNeededSize.width,
725: maxNeededSize.height
726: + HG_PUSH_PULL_VERT_PADDING);
727: }
728: p.setPreferredSize(maxNeededSize);
729: }
730: if (options != null) {
731: dialogDescriptor.setOptions(options); // NOI18N
732: }
733: showDialog(dialogDescriptor, helpCtx, name);
734: return dialogDescriptor.getValue();
735: }
736:
737: private void showDialog(DialogDescriptor dialogDescriptor,
738: HelpCtx helpCtx, String name) {
739: dialogDescriptor.setModal(true);
740: dialogDescriptor.setHelpCtx(helpCtx);
741:
742: Dialog dialog = DialogDisplayer.getDefault().createDialog(
743: dialogDescriptor);
744: if (name != null) {
745: dialog
746: .addWindowListener(new DialogBoundsPreserver(
747: HgModuleConfig.getDefault()
748: .getPreferences(), name)); // NOI18N
749: }
750: dialog.getAccessibleContext().setAccessibleDescription(
751: NbBundle.getMessage(Repository.class,
752: "ACSD_RepositoryPanel"));
753:
754: dialog.setVisible(true);
755: }
756:
757: private boolean isSet(int flag) {
758: return (modeMask & flag) != 0;
759: }
760:
761: public class RepositoryModel extends DefaultComboBoxModel {
762:
763: public RepositoryModel(Vector v) {
764: super (v);
765: }
766:
767: public void setSelectedItem(Object obj) {
768: if (obj instanceof String) {
769: int idx = getIndexOf(obj);
770: if (idx > -1) {
771: obj = getElementAt(idx);
772: } else {
773: obj = createNewRepositoryConnection((String) obj);
774: }
775: }
776: super .setSelectedItem(obj);
777: }
778:
779: public int getIndexOf(Object obj) {
780: if (obj instanceof String) {
781: obj = createNewRepositoryConnection((String) obj);
782: }
783: return super .getIndexOf(obj);
784: }
785:
786: public void addElement(Object obj) {
787: if (obj instanceof String) {
788: obj = createNewRepositoryConnection((String) obj);
789: }
790: super .addElement(obj);
791: }
792:
793: public void insertElementAt(Object obj, int index) {
794: if (obj instanceof String) {
795: String str = (String) obj;
796: RepositoryConnection rc = null;
797: try {
798: rc = (RepositoryConnection) getElementAt(index);
799: } catch (ArrayIndexOutOfBoundsException e) {
800: }
801: if (rc != null) {
802: rc.setUrl(str);
803: obj = rc;
804: }
805: obj = createNewRepositoryConnection(str);
806: }
807: super .insertElementAt(obj, index);
808: }
809:
810: public void removeElement(Object obj) {
811: int index = getIndexOf(obj);
812: if (index != -1) {
813: removeElementAt(index);
814: }
815: }
816:
817: private RepositoryConnection createNewRepositoryConnection(
818: String url) {
819: editedRC.setUrl(url);
820: return new RepositoryConnection(editedRC);
821: }
822: }
823: }
|