一般来说,我想创建一个创建多个文件的Netbeans(7.4)文件向导。
在我的情况下,我希望它在加载fxml文件时创建JavaFX相关文件以使用约定优于配置方法。 (我从Adam Bien那里接过了这个想法:http://www.youtube.com/watch?v=mawFd4h1Or4)
更具体:我想输入一个定义Basename
的字符串,并希望向导创建3个不同的文件,位于Rightclick - >的包中。用户调用了“新建”向导。
Basename.fxml
BasenameController.java
BasenameView.java
我现在尝试编写自己的向导近3天,但它无法正常工作。我研究过(瘦)Netbeans API并仔细阅读所有这些教程(及更多):
我尝试了更多的东西然后我可以在这里列举,但这些是一些令人满意的事情:
@TemplateRegistration
和多个content
条目。@TemplateRegistrations
注册了多个模板,每个我想要创建的文件都有一个模板。相关问题,对我没有帮助:
非常欢迎任何建议。提前谢谢!
更新
我设法创建了所需的文件。问题是你 使用稀疏记录的命名约定。如果要正确创建Basename.java
文件,则必须命名模板文件:Basename.java
(这会使编译器不满意,因为模板文件不是有效的java类),或 Basename.java.template
即可。如果您将其命名为:Basename.java.templ
(并自行管理文件的正确命名),则不会为您设置${package}
变量。
所以现在我非常接近我想要的,但是仍然存在正确注册向导的问题。
目前我正在使用@TemplateRegistrations
注册3个模板(每个文件一个)。但由于“文件夹”属性是强制性的,我现在在Netbeans的“新建”向导中有3个条目。当我调用其中一个时,它将根据需要创建所有3个文件,但我想在“新建”向导中只有1个条目。
@TemplateRegistrations({
@TemplateRegistration(content = "FXML.fxml.template", scriptEngine = "freemarker", folder = "ASpecial", displayName = "#TemplateName", iconBase = "de/ekrnrw/fxmlview/view.png", description = "newFXMLView.html"),
@TemplateRegistration(content = "View.java.template", scriptEngine = "freemarker", folder = "ASpecial"),
@TemplateRegistration(content = "Controller.java.template", scriptEngine = "freemarker", folder = "ASpecial")
})
我尝试使用包含多个内容条目的单个@TemplateRegistration
,但这不适用于本教程中的代码。似乎只有fxml文件被处理为freemarker,而且这两个java文件只是模板文件的纯文本副本。
@TemplateRegistration(content = {"FXML.fxml.template","View.java.template","Controller.java.template"}, scriptEngine = "freemarker", folder = "ASpecial", displayName = "#TemplateName", iconBase = "de/ekrnrw/fxmlview/view.png", description = "newFXMLView.html")
我将此问题发布到NetBeans邮件列表here。这是相关的代码片段:
package de.ekrnrw.fxmlview;
import java.awt.Component;
...
import org.openide.util.NbBundle.Messages;
@TemplateRegistrations({
@TemplateRegistration(content = "FXML.fxml.template", scriptEngine = "freemarker", folder = "ASpecial", displayName = "#TemplateName", iconBase = "de/ekrnrw/fxmlview/view.png", description = "newFXMLView.html"),
@TemplateRegistration(content = "View.java.template", scriptEngine = "freemarker", folder = "ASpecial"),
@TemplateRegistration(content = "Controller.java.template", scriptEngine = "freemarker", folder = "ASpecial")
})
// Would like to use this, but i can't make it work.
//@TemplateRegistration(content = {"FXML.fxml.template","View.java.template","Controller.java.template"}, scriptEngine = "freemarker", folder = "ASpecial", displayName = "#TemplateName", iconBase = "de/ekrnrw/fxmlview/view.png", description = "newFXMLView.html")
@Messages("TemplateName=FXMLView4")
public final class NewFXMLViewWizardIterator implements WizardDescriptor.InstantiatingIterator<WizardDescriptor> {
private int index;
private WizardDescriptor wizard;
private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
if (panels == null) {
panels = new ArrayList<>();
// Change to default new file panel and add our panel at bottom
Project p = Templates.getProject(wizard);
SourceGroup[] groups = ProjectUtils.getSources(p).getSourceGroups(Sources.TYPE_GENERIC);
// SimpleTargetChooser is the default new file panel
WizardDescriptor.Panel<WizardDescriptor> advNewFilePanel = Templates.buildSimpleTargetChooser(p, groups).create();
panels.add(advNewFilePanel);
String[] steps = createSteps();
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
if (steps[i] == null) {
// Default step name to component name of panel. Mainly
// useful for getting the name of the target chooser to
// appear in the list of steps.
steps[i] = c.getName();
}
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
}
}
}
return panels;
}
@Override
public Set<?> instantiate() throws IOException {
//Get the folder:
FileObject dir = Templates.getTargetFolder(wizard);
DataFolder df = DataFolder.findFolder(dir);
//Get TargetName from File Wizard
String targetName = Templates.getTargetName(wizard);
// Read Title from wizard
String viewName = targetName + "View";
String controllerName = targetName + "Controller";
// FreeMarker Template will get its variables from HashMap.
// HashMap key is the variable name.
Map args = new HashMap();
args.put("controllerName", controllerName);
args.put("viewName", viewName);
//Get Templates
FileObject[] templates = Templates.getTemplate(wizard).getParent().getChildren();
// Create all Files
Set<DataObject> createdObjects = new HashSet<>();
for (FileObject fileObject : templates) {
DataObject dTemplate = DataObject.find(fileObject);
String templateName = dTemplate.getName();
// Sepcial treatment for the .fxml file.
if (templateName.equals("FXML")) {
templateName = "";
}
// Create file
createdObjects.add(dTemplate.createFromTemplate(df, targetName + templateName , args));
}
return createdObjects;
}
...
}
答案 0 :(得分:1)
请在邮件列表dev@platform.netbeans.org询问并提供非工作样本,以便重现该问题。
答案 1 :(得分:1)
我尝试了你的样品,我查了一下。您不需要使用@TemplateRegistration注释来使用freemarker,也不需要使用Templates.getTemplate(wizard).getParent().getChildren()
FileObject template1 = FileUtil.getConfigFile("CustomerSalesTemplates/project1.txt");
DataObject dTemplate1 = DataObject.find(template1);
dTemplate1.createFromTemplate
调用freemarker 查看文章 * https://blogs.oracle.com/geertjan/entry/how_to_visually_diff_multiple * https://blogs.oracle.com/geertjan/entry/freemarker_baked_into_netbeans_ide1
答案 2 :(得分:0)
在构建时,所有@TemplateRegistration
注释都将转换为名为layer.xml
的文件中的文件条目。在layer.xml
中,文件模板显示如下:
<filesystem>
<folder name="Templates">
<folder name="javafx">
<file name="FxmlNode.java" url="nbresloc:/tuupertunut/fxmltemplates/FxmlNode.java.template">
<attr name="template" boolvalue="true"/>
<attr name="displayName" bundlevalue="tuupertunut.fxmltemplates.Bundle#FxmlNode_displayName"/>
<attr name="iconBase" stringvalue="org/netbeans/spi/java/project/support/ui/templates/class.png"/>
<attr name="instantiatingWizardURL" urlvalue="nbresloc:/tuupertunut/fxmltemplates/FxmlNodeDescription.html"/>
<attr name="instantiatingIterator" newvalue="tuupertunut.fxmltemplates.FxmlNodeIterator"/>
<attr name="requireProject" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
</file>
</folder>
</folder>
</filesystem>
您可以看到具有file
属性的attr
条目。与您的问题相关的属性为template
和javax.script.ScriptEngine
。
file
的每个<attr name="template"
boolvalue="true"/>
条目都会在“新建”中显示为单独的条目
文件“对话框。file
条目都有<attr
name="javax.script.ScriptEngine" stringvalue="freemarker"/>
在创建文件之前由freemarker处理。@TemplateRegistration
s @TemplateRegistrations({
@TemplateRegistration(content = "FXML.fxml.template", scriptEngine = "freemarker", folder = "ASpecial", ...),
@TemplateRegistration(content = "View.java.template", scriptEngine = "freemarker", folder = "ASpecial"),
@TemplateRegistration(content = "Controller.java.template", scriptEngine = "freemarker", folder = "ASpecial")
})
将转换为
<filesystem>
<folder name="Templates">
<folder name="ASpecial">
<file name="FXML.fxml" url="nbresloc:/yourpackage/FXML.fxml.template">
<attr name="template" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
<file name="View.java" url="nbresloc:/yourpackage/View.java.template">
<attr name="template" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
<file name="Controller.java" url="nbresloc:/yourpackage/Controller.java.template">
<attr name="template" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
</folder>
</folder>
</filesystem>
如您所见,所有三个模板都将显示在“新文件”对话框中,所有三个模板都将由freemarker处理。
content
@TemplateRegistration
@TemplateRegistration(content = {"FXML.fxml.template","View.java.template","Controller.java.template"}, scriptEngine = "freemarker", folder = "ASpecial", ...)
将转换为
<filesystem>
<folder name="Templates">
<folder name="ASpecial">
<file name="FXML.fxml" url="nbresloc:/yourpackage/FXML.fxml.template">
<attr name="template" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
<file name="View.java" url="nbresloc:/yourpackage/View.java.template">
...
</file>
<file name="Controller.java" url="nbresloc:/yourpackage/Controller.java.template">
...
</file>
</folder>
</folder>
</filesystem>
此处只有第一个模板会显示在“新文件”对话框中,而且只有第一个模板将由freemarker处理。
由于注释不会产生所需的layer.xml
,因此您必须自己创建一个注释。您应该能够从项目的generated-layer.xml
目录中找到自动生成的build/classes/META-INF
。从“新建文件”对话框中为项目创建一个新的layer.xml
文件,然后将所有内容复制粘贴到其中。然后,您可以手动编辑这些template
和javax.script.ScriptEngine
属性。
最后,看起来应该是这样的:
<filesystem>
<folder name="Templates">
<folder name="ASpecial">
<file name="FXML.fxml" url="nbresloc:/yourpackage/FXML.fxml.template">
<attr name="template" boolvalue="true"/>
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
<file name="View.java" url="nbresloc:/yourpackage/View.java.template">
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
<file name="Controller.java" url="nbresloc:/yourpackage/Controller.java.template">
<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
...
</file>
</folder>
</folder>
</filesystem>
第一个条目是template
唯一的条目,但所有条目都javax.script.ScriptEngine
不要忘记删除@TemplateRegistration
注释,因为模板现在由layer.xml
管理。