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-2007 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.ruby.rubyproject.templates;
043:
044: import java.awt.Component;
045: import java.awt.Dimension;
046: import java.awt.event.ActionListener;
047: import java.io.File;
048: import java.util.ArrayList;
049: import java.util.List;
050: import javax.swing.DefaultComboBoxModel;
051: import javax.swing.DefaultListCellRenderer;
052: import javax.swing.JFileChooser;
053: import javax.swing.JList;
054: import javax.swing.JPanel;
055: import javax.swing.SwingUtilities;
056: import javax.swing.SwingUtilities;
057: import javax.swing.SwingUtilities;
058: import javax.swing.event.ChangeEvent;
059: import javax.swing.event.ChangeListener;
060: import javax.swing.event.DocumentEvent;
061: import javax.swing.event.DocumentListener;
062: import javax.swing.text.AbstractDocument;
063: import javax.swing.text.BadLocationException;
064: import javax.swing.text.Document;
065: import javax.swing.text.JTextComponent;
066: import org.netbeans.api.project.Project;
067: import org.netbeans.api.project.ProjectUtils;
068: import org.netbeans.api.project.SourceGroup;
069: import org.netbeans.modules.ruby.RubyUtils;
070: import org.netbeans.modules.ruby.spi.project.support.rake.PropertyUtils;
071: import org.openide.filesystems.FileObject;
072: import org.openide.filesystems.FileUtil;
073: import org.openide.awt.Mnemonics;
074: import org.openide.loaders.DataObject;
075: import org.openide.loaders.DataObjectNotFoundException;
076: import org.openide.util.Exceptions;
077: import org.openide.util.NbBundle;
078:
079: /**
080: * Permits user to select a floder to place a Ruby file (or other resource) into.
081: * @author Petr Hrebejk, Jesse Glick, Tor Norbye
082: */
083: public class RubyTargetChooserPanelGUI extends JPanel implements
084: ActionListener, DocumentListener {
085:
086: private static final String NEW_CLASS_PREFIX = NbBundle.getMessage(
087: RubyTargetChooserPanelGUI.class,
088: "LBL_RubyTargetChooserPanelGUI_NewRubyClassPrefix"); // NOI18N
089:
090: /** preferred dimension of the panel */
091: private static final Dimension PREF_DIM = new Dimension(500, 340);
092:
093: private Project project;
094: /** File set except for when we're manually updating values in some of the
095: * dependent text fields */
096: private boolean userEdit = true;
097: /** Flag used to keep track of whether the user has edited the file field manually */
098: private boolean fileEdited;
099: /** Flag used to keep track of whether the user has edited the class field manually */
100: private boolean classEdited;
101: private String expectedExtension;
102: private final List<ChangeListener> listeners = new ArrayList<ChangeListener>();
103: private int type;
104: private SourceGroup groups[];
105:
106: //private boolean ignoreRootCombo;
107:
108: /** Creates new form SimpleTargetChooserGUI */
109: public RubyTargetChooserPanelGUI(Project p, SourceGroup[] groups,
110: Component bottomPanel, int type) {
111: this .type = type;
112: this .project = p;
113: this .groups = groups;
114:
115: initComponents();
116:
117: // NOTE - even when adding a -module-, we will use the "class" textfield
118: // to represent the name of the module, and the "module" text field to represent
119: // modules surrounding the current module
120: if (type == NewRubyFileWizardIterator.TYPE_TEST) {
121: extendsText.setText("Test::Unit::TestCase"); // NOI18N
122: type = this .type = NewRubyFileWizardIterator.TYPE_CLASS;
123: }
124:
125: if (type == NewRubyFileWizardIterator.TYPE_CLASS
126: || type == NewRubyFileWizardIterator.TYPE_MODULE) {
127: if (type == NewRubyFileWizardIterator.TYPE_MODULE) {
128: extendsLabel.setVisible(false);
129: extendsText.setVisible(false);
130: Mnemonics
131: .setLocalizedText(
132: classLabel,
133: NbBundle
134: .getMessage(
135: RubyTargetChooserPanelGUI.class,
136: "LBL_RubyTargetChooserPanelGUI_ModuleName_Label")); // NOI18N
137: } else {
138: extendsText.getDocument().addDocumentListener(this );
139: }
140: moduleText.getDocument().addDocumentListener(this );
141: classText.getDocument().addDocumentListener(this );
142: } else if (type == NewRubyFileWizardIterator.TYPE_SPEC) {
143: Mnemonics.setLocalizedText(classLabel, NbBundle.getMessage(
144: RubyTargetChooserPanelGUI.class,
145: "LBL_RubyTargetChooserPanelGUI_Spec_Class")); // NOI18N
146: moduleLabel.setVisible(false);
147: moduleText.setVisible(false);
148: extendsLabel.setVisible(false);
149: extendsText.setVisible(false);
150: classText.getDocument().addDocumentListener(this );
151: } else {
152: // TYPE_FILE
153: classLabel.setVisible(false);
154: classText.setVisible(false);
155: moduleLabel.setVisible(false);
156: moduleText.setVisible(false);
157: extendsLabel.setVisible(false);
158: extendsText.setVisible(false);
159: }
160:
161: documentNameTextField.getDocument().addDocumentListener(this );
162:
163: if (bottomPanel != null) {
164: bottomPanelContainer.add(bottomPanel,
165: java.awt.BorderLayout.CENTER);
166: }
167:
168: browseButton.addActionListener(this );
169: folderTextField.getDocument().addDocumentListener(this );
170:
171: //initValues( project, null, null );
172:
173: rootComboBox.setRenderer(new GroupListCellRenderer());
174: rootComboBox.addActionListener(this );
175:
176: setPreferredSize(PREF_DIM);
177: setName(NbBundle.getBundle(RubyTargetChooserPanelGUI.class)
178: .getString("LBL_RubyTargetChooserPanelGUI_Name")); // NOI18N
179: }
180:
181: @Override
182: public void addNotify() {
183: Dimension panel2Size = this .jPanel2.getPreferredSize();
184: Dimension bottomPanelSize = this .bottomPanelContainer
185: .getPreferredSize();
186: Dimension splitterSize = this .targetSeparator
187: .getPreferredSize();
188: int vmax = panel2Size.height + bottomPanelSize.height
189: + splitterSize.height + 12; //Insets=12
190: //Update only height, keep the wizard width
191: if (vmax > PREF_DIM.height) {
192: this .setPreferredSize(new Dimension(PREF_DIM.width, vmax));
193: }
194: super .addNotify();
195: }
196:
197: public void initValues(FileObject template,
198: FileObject preselectedFolder) {
199: assert project != null : "Project must be specified."; // NOI18N
200: // Show name of the project
201: projectTextField.setText(ProjectUtils.getInformation(project)
202: .getDisplayName());
203: assert template != null;
204:
205: String displayName = null;
206: try {
207: DataObject templateDo = DataObject.find(template);
208: displayName = templateDo.getNodeDelegate().getDisplayName();
209: } catch (DataObjectNotFoundException ex) {
210: displayName = template.getName();
211: }
212:
213: putClientProperty("NewFileWizard_Title", displayName);// NOI18N
214: // Setup comboboxes
215: rootComboBox.setModel(new DefaultComboBoxModel(groups));
216: SourceGroup preselectedGroup = getPreselectedGroup(
217: preselectedFolder, (Boolean) template
218: .getAttribute("isTest")); // NOI18N
219: //ignoreRootCombo = true;
220: rootComboBox.setSelectedItem(preselectedGroup);
221: if (preselectedFolder != null) {
222: folderTextField.setText(FileUtil.toFile(preselectedFolder)
223: .getPath());
224: }
225:
226: //ignoreRootCombo = false;
227:
228: if (template != null) {
229: if (documentNameTextField.getText().trim().length() == 0) { // To preserve the class name on back in the wiazard
230: //Ordinary file
231: String prefix = NEW_CLASS_PREFIX;
232: // See 91580
233: Object customPrefix = template
234: .getAttribute("templateNamePrefix"); // NOI18N
235: if (customPrefix != null) {
236: prefix = customPrefix.toString();
237: }
238:
239: if (type != NewRubyFileWizardIterator.TYPE_SPEC) {
240: documentNameTextField.setText(prefix
241: + template.getName());
242: }
243: documentNameTextField.selectAll();
244: }
245: }
246:
247: // Determine the extension
248: String ext = template == null ? "" : template.getExt(); // NOI18N
249: expectedExtension = ext.length() == 0 ? "" : "." + ext; // NOI18N
250:
251: updateText();
252: fileEdited = false;
253: classEdited = false;
254: if (type == NewRubyFileWizardIterator.TYPE_CLASS
255: || type == NewRubyFileWizardIterator.TYPE_MODULE) {
256: classText.selectAll();
257: }
258: }
259:
260: public FileObject getRootFolder() {
261: return ((SourceGroup) rootComboBox.getSelectedItem())
262: .getRootFolder();
263: }
264:
265: public String getTargetFolder() {
266:
267: String folderName = folderTextField.getText().trim();
268:
269: if (folderName.length() == 0) {
270: return null;
271: } else {
272: return folderName.replace(File.separatorChar, '/'); // NOI18N
273: }
274: }
275:
276: public String getTargetName() {
277: String text = documentNameTextField.getText().trim();
278:
279: if (text.length() == 0) {
280: return null;
281: } else {
282: return text;
283: }
284:
285: }
286:
287: public String getClassName() {
288: String text = classText.getText().trim();
289:
290: if (text.length() == 0) {
291: return null;
292: } else {
293: return text;
294: }
295: }
296:
297: public String getModuleName() {
298: String text = moduleText.getText().trim();
299:
300: if (text.length() == 0) {
301: return null;
302: } else {
303: return text;
304: }
305: }
306:
307: public String getExtends() {
308: String text = extendsText.getText().trim();
309:
310: if (text.length() == 0) {
311: return null;
312: } else {
313: return text;
314: }
315: }
316:
317: public void addChangeListener(ChangeListener l) {
318: listeners.add(l);
319: }
320:
321: public void removeChangeListener(ChangeListener l) {
322: listeners.remove(l);
323: }
324:
325: private void fireChange() {
326: ChangeEvent e = new ChangeEvent(this );
327: for (ChangeListener l : listeners) {
328: l.stateChanged(e);
329: }
330: }
331:
332: /** This method is called from within the constructor to
333: * initialize the form.
334: * WARNING: Do NOT modify this code. The content of this method is
335: * always regenerated by the Form Editor.
336: */
337: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
338: private void initComponents() {
339: java.awt.GridBagConstraints gridBagConstraints;
340:
341: targetSeparator = new javax.swing.JSeparator();
342: bottomPanelContainer = new javax.swing.JPanel();
343: jPanel2 = new javax.swing.JPanel();
344: jPanel1 = new javax.swing.JPanel();
345: classLabel = new javax.swing.JLabel();
346: classText = new javax.swing.JTextField();
347: documentNameLabel = new javax.swing.JLabel();
348: documentNameTextField = new javax.swing.JTextField();
349: moduleLabel = new javax.swing.JLabel();
350: moduleText = new javax.swing.JTextField();
351: extendsLabel = new javax.swing.JLabel();
352: extendsText = new javax.swing.JTextField();
353: jLabel5 = new javax.swing.JLabel();
354: projectTextField = new javax.swing.JTextField();
355: jLabel1 = new javax.swing.JLabel();
356: rootComboBox = new javax.swing.JComboBox();
357: jLabel2 = new javax.swing.JLabel();
358: folderTextField = new javax.swing.JTextField();
359: browseButton = new javax.swing.JButton();
360: fileLabel = new javax.swing.JLabel();
361: fileTextField = new javax.swing.JTextField();
362:
363: setLayout(new java.awt.GridBagLayout());
364: gridBagConstraints = new java.awt.GridBagConstraints();
365: gridBagConstraints.gridx = 0;
366: gridBagConstraints.gridy = 1;
367: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
368: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
369: gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0);
370: add(targetSeparator, gridBagConstraints);
371:
372: bottomPanelContainer.setLayout(new java.awt.BorderLayout());
373: gridBagConstraints = new java.awt.GridBagConstraints();
374: gridBagConstraints.gridx = 0;
375: gridBagConstraints.gridy = 2;
376: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
377: gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
378: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
379: gridBagConstraints.weighty = 1.0;
380: add(bottomPanelContainer, gridBagConstraints);
381:
382: jPanel2.setLayout(new java.awt.GridBagLayout());
383:
384: jPanel1.setLayout(new java.awt.GridBagLayout());
385:
386: classLabel.setLabelFor(classText);
387: org.openide.awt.Mnemonics
388: .setLocalizedText(
389: classLabel,
390: org.openide.util.NbBundle
391: .getMessage(
392: RubyTargetChooserPanelGUI.class,
393: "LBL_RubyTargetChooserPanelGUI_ClassName_Label")); // NOI18N
394: gridBagConstraints = new java.awt.GridBagConstraints();
395: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
396: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
397: jPanel1.add(classLabel, gridBagConstraints);
398: gridBagConstraints = new java.awt.GridBagConstraints();
399: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
400: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
401: gridBagConstraints.weightx = 1.0;
402: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
403: jPanel1.add(classText, gridBagConstraints);
404:
405: documentNameLabel.setLabelFor(documentNameTextField);
406: org.openide.awt.Mnemonics
407: .setLocalizedText(
408: documentNameLabel,
409: org.openide.util.NbBundle
410: .getMessage(
411: RubyTargetChooserPanelGUI.class,
412: "LBL_RubyTargetChooserPanelGUI_FileName_Label")); // NOI18N
413: gridBagConstraints = new java.awt.GridBagConstraints();
414: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
415: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
416: jPanel1.add(documentNameLabel, gridBagConstraints);
417: gridBagConstraints = new java.awt.GridBagConstraints();
418: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
419: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
420: gridBagConstraints.weightx = 1.0;
421: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
422: jPanel1.add(documentNameTextField, gridBagConstraints);
423: java.util.ResourceBundle bundle = java.util.ResourceBundle
424: .getBundle("org/netbeans/modules/ruby/rubyproject/templates/Bundle"); // NOI18N
425: documentNameTextField.getAccessibleContext()
426: .setAccessibleDescription(
427: bundle.getString("AD_documentNameTextField")); // NOI18N
428:
429: moduleLabel.setLabelFor(moduleText);
430: org.openide.awt.Mnemonics
431: .setLocalizedText(
432: moduleLabel,
433: org.openide.util.NbBundle
434: .getMessage(
435: RubyTargetChooserPanelGUI.class,
436: "LBL_RubyTargetChooserPanelGUI_InModuleName_Label")); // NOI18N
437: gridBagConstraints = new java.awt.GridBagConstraints();
438: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
439: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
440: jPanel1.add(moduleLabel, gridBagConstraints);
441: gridBagConstraints = new java.awt.GridBagConstraints();
442: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
443: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
444: gridBagConstraints.weightx = 1.0;
445: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
446: jPanel1.add(moduleText, gridBagConstraints);
447:
448: extendsLabel.setLabelFor(extendsText);
449: org.openide.awt.Mnemonics.setLocalizedText(extendsLabel,
450: org.openide.util.NbBundle.getMessage(
451: RubyTargetChooserPanelGUI.class,
452: "LBL_RubyTargetChooserPanelGUI_Extends_Label")); // NOI18N
453: gridBagConstraints = new java.awt.GridBagConstraints();
454: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
455: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
456: jPanel1.add(extendsLabel, gridBagConstraints);
457: gridBagConstraints = new java.awt.GridBagConstraints();
458: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
459: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
460: gridBagConstraints.weightx = 1.0;
461: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
462: jPanel1.add(extendsText, gridBagConstraints);
463:
464: gridBagConstraints = new java.awt.GridBagConstraints();
465: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
466: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
467: gridBagConstraints.weightx = 1.0;
468: gridBagConstraints.insets = new java.awt.Insets(0, 0, 24, 0);
469: jPanel2.add(jPanel1, gridBagConstraints);
470:
471: jLabel5.setLabelFor(projectTextField);
472: org.openide.awt.Mnemonics.setLocalizedText(jLabel5,
473: org.openide.util.NbBundle.getMessage(
474: RubyTargetChooserPanelGUI.class,
475: "LBL_RubyTargetChooserPanelGUI_jLabel5")); // NOI18N
476: gridBagConstraints = new java.awt.GridBagConstraints();
477: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
478: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
479: jPanel2.add(jLabel5, gridBagConstraints);
480:
481: projectTextField.setEditable(false);
482: gridBagConstraints = new java.awt.GridBagConstraints();
483: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
484: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
485: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
486: jPanel2.add(projectTextField, gridBagConstraints);
487: projectTextField.getAccessibleContext()
488: .setAccessibleDescription(
489: bundle.getString("AD_projectTextField")); // NOI18N
490:
491: jLabel1.setLabelFor(rootComboBox);
492: org.openide.awt.Mnemonics.setLocalizedText(jLabel1,
493: org.openide.util.NbBundle.getMessage(
494: RubyTargetChooserPanelGUI.class,
495: "LBL_RubyTargetChooserPanelGUI_jLabel1")); // NOI18N
496: gridBagConstraints = new java.awt.GridBagConstraints();
497: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
498: gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
499: jPanel2.add(jLabel1, gridBagConstraints);
500: gridBagConstraints = new java.awt.GridBagConstraints();
501: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
502: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
503: gridBagConstraints.weightx = 1.0;
504: gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
505: jPanel2.add(rootComboBox, gridBagConstraints);
506: rootComboBox.getAccessibleContext().setAccessibleDescription(
507: bundle.getString("AD_rootComboBox")); // NOI18N
508:
509: org.openide.awt.Mnemonics.setLocalizedText(jLabel2,
510: org.openide.util.NbBundle.getMessage(
511: RubyTargetChooserPanelGUI.class,
512: "LBL_RubyTargetChooserPanelGUI_Folder")); // NOI18N
513: gridBagConstraints = new java.awt.GridBagConstraints();
514: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
515: gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0);
516: jPanel2.add(jLabel2, gridBagConstraints);
517: gridBagConstraints = new java.awt.GridBagConstraints();
518: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
519: gridBagConstraints.weightx = 1.0;
520: gridBagConstraints.insets = new java.awt.Insets(0, 6, 12, 0);
521: jPanel2.add(folderTextField, gridBagConstraints);
522:
523: org.openide.awt.Mnemonics.setLocalizedText(browseButton,
524: org.openide.util.NbBundle.getMessage(
525: RubyTargetChooserPanelGUI.class,
526: "LBL_RubyTargetChooserPanelGUI_Browse")); // NOI18N
527: gridBagConstraints = new java.awt.GridBagConstraints();
528: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
529: gridBagConstraints.insets = new java.awt.Insets(0, 6, 12, 0);
530: jPanel2.add(browseButton, gridBagConstraints);
531:
532: fileLabel.setLabelFor(fileTextField);
533: org.openide.awt.Mnemonics
534: .setLocalizedText(
535: fileLabel,
536: org.openide.util.NbBundle
537: .getMessage(
538: RubyTargetChooserPanelGUI.class,
539: "LBL_RubyTargetChooserPanelGUI_CreatedFile_Label")); // NOI18N
540: gridBagConstraints = new java.awt.GridBagConstraints();
541: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
542: gridBagConstraints.insets = new java.awt.Insets(6, 0, 12, 0);
543: jPanel2.add(fileLabel, gridBagConstraints);
544:
545: fileTextField.setEditable(false);
546: gridBagConstraints = new java.awt.GridBagConstraints();
547: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
548: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
549: gridBagConstraints.weightx = 1.0;
550: gridBagConstraints.insets = new java.awt.Insets(6, 6, 12, 0);
551: jPanel2.add(fileTextField, gridBagConstraints);
552: fileTextField.getAccessibleContext().setAccessibleDescription(
553: bundle.getString("AD_fileTextField")); // NOI18N
554:
555: gridBagConstraints = new java.awt.GridBagConstraints();
556: gridBagConstraints.gridx = 0;
557: gridBagConstraints.gridy = 0;
558: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
559: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
560: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
561: gridBagConstraints.weightx = 1.0;
562: add(jPanel2, gridBagConstraints);
563:
564: getAccessibleContext().setAccessibleDescription(
565: bundle.getString("AD_RubyTargetChooserPanelGUI")); // NOI18N
566: }// </editor-fold>//GEN-END:initComponents
567:
568: // Variables declaration - do not modify//GEN-BEGIN:variables
569: private javax.swing.JPanel bottomPanelContainer;
570: private javax.swing.JButton browseButton;
571: private javax.swing.JLabel classLabel;
572: private javax.swing.JTextField classText;
573: private javax.swing.JLabel documentNameLabel;
574: private javax.swing.JTextField documentNameTextField;
575: private javax.swing.JLabel extendsLabel;
576: private javax.swing.JTextField extendsText;
577: private javax.swing.JLabel fileLabel;
578: private javax.swing.JTextField fileTextField;
579: private javax.swing.JTextField folderTextField;
580: private javax.swing.JLabel jLabel1;
581: private javax.swing.JLabel jLabel2;
582: private javax.swing.JLabel jLabel5;
583: private javax.swing.JPanel jPanel1;
584: private javax.swing.JPanel jPanel2;
585: private javax.swing.JLabel moduleLabel;
586: private javax.swing.JTextField moduleText;
587: private javax.swing.JTextField projectTextField;
588: private javax.swing.JComboBox rootComboBox;
589: private javax.swing.JSeparator targetSeparator;
590:
591: // End of variables declaration//GEN-END:variables
592:
593: // ActionListener implementation -------------------------------------------
594:
595: public void actionPerformed(java.awt.event.ActionEvent e) {
596: if (browseButton == e.getSource()) {
597: JFileChooser chooser = new JFileChooser();
598: FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
599: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
600: chooser.setMultiSelectionEnabled(false);
601:
602: String workDir = folderTextField.getText();
603: if (workDir.length() > 0) {
604: File workdirFile = new File(workDir);
605: chooser.setSelectedFile(workdirFile);
606: chooser.setCurrentDirectory(workdirFile);
607: }
608: chooser.setDialogTitle(NbBundle.getMessage(
609: RubyTargetChooserPanelGUI.class,
610: "ChooseTargetFolder"));
611: if (JFileChooser.APPROVE_OPTION == chooser
612: .showOpenDialog(this )) { //NOI18N
613: File file = FileUtil.normalizeFile(chooser
614: .getSelectedFile());
615: folderTextField.setText(file.getAbsolutePath());
616: }
617: updateText();
618: fireChange();
619: } else if (rootComboBox == e.getSource()) {
620: FileObject root = ((SourceGroup) rootComboBox
621: .getSelectedItem()).getRootFolder();
622: folderTextField.setText(FileUtil.toFile(root).getPath());
623: updateText();
624: fireChange();
625: }
626: }
627:
628: // DocumentListener implementation -----------------------------------------
629:
630: public void changedUpdate(javax.swing.event.DocumentEvent e) {
631: trackEdit(e);
632: updateText();
633: fireChange();
634: }
635:
636: public void insertUpdate(javax.swing.event.DocumentEvent e) {
637: changedUpdate(e);
638: }
639:
640: public void removeUpdate(javax.swing.event.DocumentEvent e) {
641: changedUpdate(e);
642: }
643:
644: private void syncFields(JTextComponent textComponent, String value) {
645: try {
646: userEdit = false;
647: textComponent.setText(value);
648: } finally {
649: userEdit = true;
650: }
651: }
652:
653: private void capitalizeFirstChar(final JTextComponent field,
654: DocumentEvent e) {
655: if (e.getType() == DocumentEvent.EventType.REMOVE) {
656: // Don't change the first char when you're deleting it - it would
657: // capitalize the second letter which is inconvenient when you're
658: // backspacing up to change the word
659: return;
660: }
661:
662: String text = field.getText().trim();
663: if (text.length() > 0 && Character.isLowerCase(text.charAt(0))) {
664: // Force uppercase names to help lazy typists
665: SwingUtilities.invokeLater(new Runnable() {
666: public void run() {
667: String text = field.getText().trim();
668: if (text.length() > 0
669: && Character.isLowerCase(text.charAt(0))) {
670: boolean wasEditing = userEdit;
671: try {
672: userEdit = false;
673: ((AbstractDocument) field.getDocument())
674: .replace(
675: 0,
676: 1,
677: ""
678: + Character
679: .toUpperCase(text
680: .charAt(0)),
681: null);
682: } catch (BadLocationException ble) {
683: Exceptions.printStackTrace(ble);
684: } finally {
685: userEdit = wasEditing;
686: }
687: }
688: }
689: });
690: }
691: }
692:
693: private void trackEdit(DocumentEvent e) {
694: if (userEdit) {
695: Document doc = e.getDocument();
696: if (doc == documentNameTextField.getDocument()) {
697: fileEdited = true;
698:
699: String text = documentNameTextField.getText().trim();
700: if (text.length() == 0) {
701: fileEdited = false;
702: }
703: if (type == NewRubyFileWizardIterator.TYPE_SPEC
704: && (!classEdited || classText.getText()
705: .length() == 0)) {
706: classEdited = false;
707: if (text.endsWith("_spec")) { // NOI18N
708: syncFields(classText, text.substring(0, text
709: .length()
710: - "_spec".length())); // NOI18N
711: }
712: } else if ((type == NewRubyFileWizardIterator.TYPE_CLASS || type == NewRubyFileWizardIterator.TYPE_MODULE)
713: && (!classEdited || classText.getText()
714: .length() == 0)) {
715: classEdited = false;
716: syncFields(classText, RubyUtils
717: .underlinedNameToCamel(text));
718: }
719: } else if (doc == classText.getDocument()) {
720: if (e.getType() != DocumentEvent.EventType.REMOVE) {
721: capitalizeFirstChar(classText, e);
722: }
723: classEdited = true;
724:
725: if (!fileEdited
726: || documentNameTextField.getText().trim()
727: .length() == 0) {
728: fileEdited = false;
729: String text = classText.getText().trim();
730: if (type == NewRubyFileWizardIterator.TYPE_SPEC
731: && text.length() > 0) {
732: syncFields(documentNameTextField, RubyUtils
733: .camelToUnderlinedName(text)
734: + "_spec"); // NOI18N
735: } else {
736: syncFields(documentNameTextField, RubyUtils
737: .camelToUnderlinedName(text));
738: }
739: }
740: } else if (doc == extendsText.getDocument()) {
741: capitalizeFirstChar(extendsText, e);
742: } else if (doc == moduleText.getDocument()) {
743: capitalizeFirstChar(moduleText, e);
744: }
745: }
746: }
747:
748: // Private methods ---------------------------------------------------------
749:
750: private void updateText() {
751: String folderName = folderTextField.getText().trim();
752:
753: String documentName = documentNameTextField.getText().trim();
754: if (documentName.length() > 0) {
755: documentName = documentName + expectedExtension;
756: }
757: String createdFileName = folderName
758: + (folderName.endsWith("/")
759: || folderName.endsWith(File.separator)
760: || folderName.length() == 0 ? "" : "/") + // NOI18N
761: documentName;
762:
763: fileTextField.setText(createdFileName.replace('/',
764: File.separatorChar)); // NOI18N
765: }
766:
767: private SourceGroup getPreselectedGroup(final FileObject folder,
768: final Boolean isTest) {
769: for (int i = 0; folder != null && i < groups.length; i++) {
770: FileObject root = groups[i].getRootFolder();
771: if (root.equals(folder)
772: || FileUtil.isParentOf(root, folder)) {
773: return groups[i];
774: }
775: }
776: if (isTest != null && isTest) { // #118440
777: for (SourceGroup group : groups) {
778: String relPath = PropertyUtils.relativizeFile(FileUtil
779: .toFile(project.getProjectDirectory()),
780: FileUtil.toFile(group.getRootFolder()));
781: // standard project (test) and rails(test/unit)
782: if ("test".equals(relPath)
783: || "test/unit".equals(relPath)) { // NOI18N
784: return group;
785: }
786: }
787: }
788: return groups[0];
789: }
790:
791: // private String getRelativeNativeName( FileObject root, FileObject folder ) {
792: // if (root == null) {
793: // throw new NullPointerException("null root passed to getRelativeNativeName"); // NOI18N
794: // }
795: //
796: // String path;
797: //
798: // if (folder == null) {
799: // path = ""; // NOI18N
800: // }
801: // else {
802: // path = FileUtil.getRelativePath( root, folder );
803: // }
804: //
805: // return path == null ? "" : path.replace( '/', File.separatorChar ); // NOI18N
806: // }
807:
808: // Private innerclasses ----------------------------------------------------
809:
810: /**
811: * Displays a {@link SourceGroup} in {@link #rootComboBox}.
812: */
813: private static final class GroupListCellRenderer extends
814: DefaultListCellRenderer/*<SourceGroup>*/{
815:
816: public GroupListCellRenderer() {
817: }
818:
819: @Override
820: public Component getListCellRendererComponent(JList list,
821: Object value, int index, boolean isSelected,
822: boolean cellHasFocus) {
823: SourceGroup g = (SourceGroup) value;
824: super
825: .getListCellRendererComponent(list, g
826: .getDisplayName(), index, isSelected,
827: cellHasFocus);
828: setIcon(g.getIcon(false));
829: return this;
830: }
831:
832: }
833:
834: }
|