blob: e95e0c482930de44331c44353d392ae15cd2e08c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.project.ui;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.SourceGroup;
import static org.netbeans.modules.project.ui.Bundle.*;
import org.netbeans.modules.project.uiapi.ProjectChooserFactory;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.WizardDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle.Messages;
/**
*
* @author Petr Hrebejk
*/
final class SimpleTargetChooserPanel implements WizardDescriptor.Panel<WizardDescriptor>, ChangeListener {
private final ChangeSupport changeSupport = new ChangeSupport(this);
private SimpleTargetChooserPanelGUI gui;
private boolean includesTemplatesWithProject = true;
@NullAllowed
private Project project;
@NonNull
private SourceGroup[] folders;
private WizardDescriptor.Panel<WizardDescriptor> bottomPanel;
private WizardDescriptor wizard;
private boolean isFolder;
private boolean freeFileExtension;
private FileSystem fs;
@SuppressWarnings("LeakingThisInConstructor")
SimpleTargetChooserPanel(@NullAllowed Project project, @NonNull SourceGroup[] folders,
WizardDescriptor.Panel<WizardDescriptor> bottomPanel, boolean isFolder, boolean freeFileExtension) {
this.folders = folders;
this.project = project;
this.bottomPanel = bottomPanel;
if ( bottomPanel != null ) {
bottomPanel.addChangeListener( this );
}
this.isFolder = isFolder;
this.freeFileExtension = freeFileExtension;
this.gui = null;
}
public @Override Component getComponent() {
if (noProjectFolders()) {
return new JPanel();
}
if (gui == null) {
gui = new SimpleTargetChooserPanelGUI(project, folders, bottomPanel == null ? null : bottomPanel.getComponent(), isFolder, freeFileExtension);
gui.addChangeListener(this);
}
return gui;
}
private boolean noProjectFolders() { // #202410
// if the project is null then any folder on the system is available
return project != null && folders != null && folders.length == 0;
}
public @Override HelpCtx getHelp() {
if ( bottomPanel != null ) {
HelpCtx bottomHelp = bottomPanel.getHelp();
if ( bottomHelp != null ) {
return bottomHelp;
}
}
//XXX
return null;
}
public @Override boolean isValid() {
if (noProjectFolders()) {
return false;
}
boolean ok = ( gui != null && gui.getTargetName() != null &&
( bottomPanel == null || bottomPanel.isValid() ) );
if (!ok) {
return false;
}
// check if the file name can be created
FileObject template = Templates.getTemplate( wizard );
assert template != null : "Null template in wizard:" + wizard.getClass().getName() + ", prop WIZARD_KEY_TEMPLATE:" + wizard.getProperty( ProjectChooserFactory.WIZARD_KEY_TEMPLATE ) + ", thread:" + Thread.currentThread().getName();
FileObject rootFolder;
String targetFolder;
if (gui.getTargetGroup() != null) {
rootFolder = gui.getTargetGroup().getRootFolder();
targetFolder = gui.getTargetFolder();
}
else if (gui.getTargetFolder() != null) {
//this line will return null for non-existing folders
//FileUtil.toFileObject(FileUtil.normalizeFile(new File(gui.getTargetFolder())))
//that's suboptimal but makes the handling of the "outside of project" case easier.
//ideally we would traverse the file structure up until we find an existing folder and then compute the non-existing part
rootFolder = fs == null ? FileUtil.toFileObject(FileUtil.normalizeFile(new File(gui.getTargetFolder()))) : fs.getRoot(); // NOI18N
targetFolder = fs == null ? "" : gui.getTargetFolder();
}
else {
rootFolder = null;
targetFolder = null;
}
String errorMessage = ProjectUtilities.canUseFileName(rootFolder,
targetFolder, gui.getTargetName(), template.getExt(), isFolder, freeFileExtension);
wizard.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, errorMessage);
return errorMessage == null;
}
public @Override void addChangeListener(ChangeListener l) {
changeSupport.addChangeListener(l);
}
public @Override void removeChangeListener(ChangeListener l) {
changeSupport.removeChangeListener(l);
}
@Messages({
"SimpleTargetChooserPanelGUI_no_source_folders=No source folders in project; perhaps it has been deleted?",
"LBL_TemplatesPanel_Name=Choose File Type"
})
@Override public void readSettings(WizardDescriptor settings) {
Boolean b = (Boolean) settings.getProperty(NewFileWizard.INCLUDES_TEMPLATES_WITH_PROJECTS);
if (b != null && b.equals(Boolean.FALSE)) {
includesTemplatesWithProject = false;
}
wizard = settings;
if (noProjectFolders()) {
wizard.putProperty(WizardDescriptor.PROP_ERROR_MESSAGE, SimpleTargetChooserPanelGUI_no_source_folders());
return;
}
if ( gui == null ) {
getComponent();
}
// Try to preselect a folder
FileObject preselectedTarget = Templates.getTargetFolder( wizard );
if (preselectedTarget == null) {
if (project != null) {
preselectedTarget = project.getProjectDirectory();
}
else {
String home = System.getProperty("user.home");
if (home != null && new File(home).isDirectory()) {
preselectedTarget = FileUtil.toFileObject(FileUtil.normalizeFile(new File(home)));
}
}
}
// Try to preserve the already entered target name
String targetName = isFolder ? null : Templates.getTargetName( wizard );
// Init values
gui.initValues( Templates.getTemplate( wizard ), preselectedTarget, targetName, includesTemplatesWithProject );
//only when we don't have a file from local filesystem
if (preselectedTarget != null && FileUtil.toFile(preselectedTarget) == null) {
try {
fs = preselectedTarget.getFileSystem();
} catch (FileStateInvalidException ex) {
fs = null;
}
}
// XXX hack, TemplateWizard in final setTemplateImpl() forces new wizard's title
// this name is used in NewFileWizard to modify the title
Object substitute = gui.getClientProperty ("NewFileWizard_Title"); // NOI18N
if (substitute != null) {
wizard.putProperty ("NewFileWizard_Title", substitute); // NOI18N
}
wizard.putProperty(WizardDescriptor.PROP_CONTENT_DATA, new String[] {LBL_TemplatesPanel_Name(), LBL_SimpleTargetChooserPanel_Name()});
if ( bottomPanel != null ) {
bottomPanel.readSettings( settings );
}
}
public @Override void storeSettings(WizardDescriptor settings) {
if (noProjectFolders()) {
return;
}
if (WizardDescriptor.PREVIOUS_OPTION.equals(settings.getValue())) {
return;
}
if(!WizardDescriptor.CANCEL_OPTION.equals(settings.getValue())
&& !WizardDescriptor.CLOSED_OPTION.equals(settings.getValue()) && isValid()) {
if ( bottomPanel != null ) {
bottomPanel.storeSettings( settings );
}
if ( gui == null ) {
getComponent();
}
String name = gui.getTargetName ();
if (name != null && name.indexOf ('/') > 0) { // NOI18N
name = name.substring (name.lastIndexOf ('/') + 1);
}
Templates.setTargetFolder(settings, getTargetFolderFromGUI());
Templates.setTargetName(settings, name);
}
settings.putProperty("NewFileWizard_Title", null); // NOI18N
}
public @Override void stateChanged(ChangeEvent e) {
changeSupport.fireChange();
}
private FileObject getTargetFolderFromGUI () {
FileObject rootFolder;
String folderName;
if (gui.getTargetGroup() != null) {
rootFolder = gui.getTargetGroup().getRootFolder();
folderName = gui.getTargetFolder();
}
else if (gui.getTargetFolder() != null) {
// rootFolder = FileUtil.toFileObject(FileUtil.normalizeFile(new File(gui.getTargetFolder())));
// folderName = "";
rootFolder = fs == null ? FileUtil.toFileObject(FileUtil.normalizeFile(new File(gui.getTargetFolder()))) : fs.getRoot(); // NOI18N
folderName = fs == null ? "" : gui.getTargetFolder();
}
else {
rootFolder = null;
folderName = null;
}
String newObject = gui.getTargetName ();
if (newObject.indexOf ('/') > 0) { // NOI18N
String path = newObject.substring (0, newObject.lastIndexOf ('/')); // NOI18N
folderName = folderName == null || "".equals (folderName) ? path : folderName + '/' + path; // NOI18N
}
FileObject targetFolder;
if ( folderName == null ) {
targetFolder = rootFolder;
}
else {
targetFolder = rootFolder.getFileObject( folderName );
}
if ( targetFolder == null ) {
// XXX add deletion of the file in uninitalize ow the wizard
try {
targetFolder = FileUtil.createFolder( rootFolder, folderName );
} catch (IOException ioe) {
// Can't create the folder
throw new IllegalArgumentException(ioe); // ioe already annotated
}
}
return targetFolder;
}
}