This is an automated email from the ASF dual-hosted git repository.
cgarcia pushed a commit to branch feature/app
in repository https://gitbox.apache.org/repos/asf/plc4x-extras.git
The following commit(s) were added to refs/heads/feature/app by this push:
new d308964 WOrking in project model.
d308964 is described below
commit d308964cdcb17adcede2319bc29073a6d1ee7682
Author: César García <[email protected]>
AuthorDate: Sat Jan 17 18:05:41 2026 -0400
WOrking in project model.
---
.../malbec/malbec-projecttype/nb-configuration.xml | 21 ++
plc4j/tools/malbec/malbec-projecttype/pom.xml | 7 +-
.../projecttype/core/Plc4xProjectPanelVisual.form | 143 +++++++++++
.../projecttype/core/Plc4xProjectPanelVisual.java | 265 +++++++++++++++++++++
.../core/Plc4xProjectWizardIterator.java | 240 +++++++++++++++++++
.../projecttype/core/Plc4xProjectWizardPanel.java | 104 ++++++++
.../impl/Plc4xCustomizerProviderImpl.java | 73 ++++++
.../malbec/projecttype/impl/Plc4xProjectImpl.java | 4 +
.../impl/Plc4xProjectLogicalViewImpl.java | 18 +-
.../malbec/projecttype/nodes/TextsNodeFactory.java | 102 ++++++++
.../panels/Plc4xGeneralPropertiesImpl.java | 51 ++++
.../malbec/projecttype/core/Bundle.properties | 6 +
.../plc4x/malbec/projecttype/core/Plc4xProject.png | Bin 0 -> 336 bytes
.../projecttype/core/Plc4xProjectDescription.html | 12 +
.../projecttype/core/Plc4xProjectProject.zip | Bin 0 -> 994 bytes
15 files changed, 1038 insertions(+), 8 deletions(-)
diff --git a/plc4j/tools/malbec/malbec-projecttype/nb-configuration.xml
b/plc4j/tools/malbec/malbec-projecttype/nb-configuration.xml
new file mode 100644
index 0000000..1abd1d4
--- /dev/null
+++ b/plc4j/tools/malbec/malbec-projecttype/nb-configuration.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-shared-configuration>
+ <!--
+This file contains additional configuration written by modules in the NetBeans
IDE.
+The configuration is intended to be shared among all the users of project and
+therefore it is assumed to be part of version control checkout.
+Without this configuration present, some functionality in the IDE may be
limited or fail altogether.
+-->
+ <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
+ <!--
+Properties that influence various parts of the IDE, especially code formatting
and the like.
+You can copy and paste the single properties, into the pom.xml file and the
IDE will pick them up.
+That way multiple projects can share the same settings (useful for formatting
rules for example).
+Any value defined here will override the pom.xml file value but is only
applicable to the current project.
+-->
+
<com-github-philippefichet-sonarlint4netbeans.excludedRules>[{"repository":"php","rule":"S3335"},{"repository":"php","rule":"S3336"},{"repository":"php","rule":"S2002"},{"repository":"php","rule":"S2005"},{"repository":"php","rule":"S3333"},{"repository":"php","rule":"S3334"},{"repository":"Web","rule":"ImgWithoutWidthOrHeightCheck"},{"repository":"php","rule":"S1151"},{"repository":"php","rule":"S3332"},{"repository":"php","rule":"S2001"},{"repository":"Web","rule":"UnclosedTagC
[...]
+
<com-github-philippefichet-sonarlint4netbeans.sonarlint-preference-scope>global</com-github-philippefichet-sonarlint4netbeans.sonarlint-preference-scope>
+
<com-github-philippefichet-sonarlint4netbeans.extraProperties>{}</com-github-philippefichet-sonarlint4netbeans.extraProperties>
+
<org-netbeans-modules-javascript2-requirejs.enabled>true</org-netbeans-modules-javascript2-requirejs.enabled>
+ </properties>
+</project-shared-configuration>
diff --git a/plc4j/tools/malbec/malbec-projecttype/pom.xml
b/plc4j/tools/malbec/malbec-projecttype/pom.xml
index f3ed3ca..9696bb6 100644
--- a/plc4j/tools/malbec/malbec-projecttype/pom.xml
+++ b/plc4j/tools/malbec/malbec-projecttype/pom.xml
@@ -80,7 +80,12 @@
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-ui</artifactId>
- <version>RELEASE280</version>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-templates</artifactId>
+ <version>${netbeans.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.form
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.form
new file mode 100644
index 0000000..89558dd
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.form
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+
+ 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.
+
+-->
+
+<Form version="1.5" maxVersion="1.9"
type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer"
value="1"/>
+ <AuxValue name="FormSettings_autoSetComponentName"
type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean"
value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode"
type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean"
value="true"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer"
value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle"
type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean"
value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer"
value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" attributes="0">
+ <EmptySpace min="-2" max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Component id="projectNameLabel" alignment="0" min="-2"
max="-2" attributes="0"/>
+ <Component id="projectLocationLabel" alignment="0" min="-2"
max="-2" attributes="0"/>
+ <Component id="createdFolderLabel" alignment="0" min="-2"
max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace min="-2" max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Component id="projectNameTextField" alignment="1"
pref="191" max="32767" attributes="0"/>
+ <Component id="projectLocationTextField" alignment="1"
pref="191" max="32767" attributes="0"/>
+ <Component id="createdFolderTextField" alignment="1"
pref="191" max="32767" attributes="0"/>
+ </Group>
+ <EmptySpace min="-2" max="-2" attributes="0"/>
+ <Component id="browseButton" min="-2" max="-2" attributes="0"/>
+ <EmptySpace min="-2" max="-2" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="3" attributes="0">
+ <Component id="projectNameLabel" alignment="3" min="-2"
max="-2" attributes="0"/>
+ <Component id="projectNameTextField" alignment="3" min="-2"
max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="3" attributes="0">
+ <Component id="projectLocationLabel" alignment="3" min="-2"
max="-2" attributes="0"/>
+ <Component id="projectLocationTextField" alignment="3"
min="-2" max="-2" attributes="0"/>
+ <Component id="browseButton" alignment="3" min="-2" max="-2"
attributes="0"/>
+ </Group>
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="3" attributes="0">
+ <Component id="createdFolderLabel" alignment="3" min="-2"
max="-2" attributes="0"/>
+ <Component id="createdFolderTextField" alignment="3"
min="-2" max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace pref="213" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JLabel" name="projectNameLabel">
+ <Properties>
+ <Property name="labelFor" type="java.awt.Component"
editor="org.netbeans.modules.form.ComponentChooserEditor">
+ <ComponentRef name="projectNameTextField"/>
+ </Property>
+ <Property name="text" type="java.lang.String"
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString
bundle="org/apache/plc4x/malbec/projecttype/core/Bundle.properties"
key="Plc4xProjectPanelVisual.projectNameLabel.text"
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class,
"{key}")"/>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean"
value="true"/>
+ </AuxValues>
+ </Component>
+ <Component class="javax.swing.JTextField" name="projectNameTextField">
+ </Component>
+ <Component class="javax.swing.JLabel" name="projectLocationLabel">
+ <Properties>
+ <Property name="labelFor" type="java.awt.Component"
editor="org.netbeans.modules.form.ComponentChooserEditor">
+ <ComponentRef name="projectLocationTextField"/>
+ </Property>
+ <Property name="text" type="java.lang.String"
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString
bundle="org/apache/plc4x/malbec/projecttype/core/Bundle.properties"
key="Plc4xProjectPanelVisual.projectLocationLabel.text"
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class,
"{key}")"/>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="generateMnemonicsCode" type="java.lang.Boolean"
value="true"/>
+ </AuxValues>
+ </Component>
+ <Component class="javax.swing.JTextField" name="projectLocationTextField">
+ </Component>
+ <Component class="javax.swing.JButton" name="browseButton">
+ <Properties>
+ <Property name="text" type="java.lang.String"
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString
bundle="org/apache/plc4x/malbec/projecttype/core/Bundle.properties"
key="Plc4xProjectPanelVisual.browseButton.text"
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class,
"{key}")"/>
+ </Property>
+ <Property name="actionCommand" type="java.lang.String"
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString
bundle="org/apache/plc4x/malbec/projecttype/core/Bundle.properties"
key="Plc4xProjectPanelVisual.browseButton.actionCommand"
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class,
"{key}")"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed"
listener="java.awt.event.ActionListener"
parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
+ </Events>
+ </Component>
+ <Component class="javax.swing.JLabel" name="createdFolderLabel">
+ <Properties>
+ <Property name="labelFor" type="java.awt.Component"
editor="org.netbeans.modules.form.ComponentChooserEditor">
+ <ComponentRef name="createdFolderTextField"/>
+ </Property>
+ <Property name="text" type="java.lang.String"
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString
bundle="org/apache/plc4x/malbec/projecttype/core/Bundle.properties"
key="Plc4xProjectPanelVisual.createdFolderLabel.text"
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class,
"{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JTextField" name="createdFolderTextField">
+ <Properties>
+ <Property name="editable" type="boolean" value="false"/>
+ </Properties>
+ </Component>
+ </SubComponents>
+</Form>
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.java
new file mode 100644
index 0000000..5b4cd4c
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectPanelVisual.java
@@ -0,0 +1,265 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt
to change this license
+ * Click
nbfs://nbhost/SystemFileSystem/Templates/NetBeansModuleDevelopment-files/templatePanelVisual.java
to edit this template
+ */
+package org.apache.plc4x.malbec.projecttype.core;
+
+import java.io.File;
+import javax.swing.JFileChooser;
+import javax.swing.JPanel;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.Document;
+import org.netbeans.spi.project.ui.support.ProjectChooser;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.filesystems.FileUtil;
+
+public class Plc4xProjectPanelVisual extends JPanel implements
DocumentListener {
+
+ public static final String PROP_PROJECT_NAME = "projectName";
+
+ private Plc4xProjectWizardPanel panel;
+
+ public Plc4xProjectPanelVisual(Plc4xProjectWizardPanel panel) {
+ initComponents();
+ this.panel = panel;
+ // Register listener on the textFields to make the automatic updates
+ projectNameTextField.getDocument().addDocumentListener(this);
+ projectLocationTextField.getDocument().addDocumentListener(this);
+ }
+
+ public String getProjectName() {
+ return this.projectNameTextField.getText();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the
form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc="Generated
Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ projectNameLabel = new javax.swing.JLabel();
+ projectNameTextField = new javax.swing.JTextField();
+ projectLocationLabel = new javax.swing.JLabel();
+ projectLocationTextField = new javax.swing.JTextField();
+ browseButton = new javax.swing.JButton();
+ createdFolderLabel = new javax.swing.JLabel();
+ createdFolderTextField = new javax.swing.JTextField();
+
+ projectNameLabel.setLabelFor(projectNameTextField);
+ org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel,
org.openide.util.NbBundle.getMessage(Plc4xProjectPanelVisual.class,
"Plc4xProjectPanelVisual.projectNameLabel.text")); // NOI18N
+
+ projectLocationLabel.setLabelFor(projectLocationTextField);
+ org.openide.awt.Mnemonics.setLocalizedText(projectLocationLabel,
org.openide.util.NbBundle.getMessage(Plc4xProjectPanelVisual.class,
"Plc4xProjectPanelVisual.projectLocationLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(browseButton,
org.openide.util.NbBundle.getMessage(Plc4xProjectPanelVisual.class,
"Plc4xProjectPanelVisual.browseButton.text")); // NOI18N
+
browseButton.setActionCommand(org.openide.util.NbBundle.getMessage(Plc4xProjectPanelVisual.class,
"Plc4xProjectPanelVisual.browseButton.actionCommand")); // NOI18N
+ browseButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ browseButtonActionPerformed(evt);
+ }
+ });
+
+ createdFolderLabel.setLabelFor(createdFolderTextField);
+ org.openide.awt.Mnemonics.setLocalizedText(createdFolderLabel,
org.openide.util.NbBundle.getMessage(Plc4xProjectPanelVisual.class,
"Plc4xProjectPanelVisual.createdFolderLabel.text")); // NOI18N
+
+ createdFolderTextField.setEditable(false);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(projectNameLabel)
+ .addComponent(projectLocationLabel)
+ .addComponent(createdFolderLabel))
+
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(projectNameTextField,
javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
+ .addComponent(projectLocationTextField,
javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
+ .addComponent(createdFolderTextField,
javax.swing.GroupLayout.Alignment.TRAILING,
javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE))
+
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(browseButton)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(projectNameLabel)
+ .addComponent(projectNameTextField,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
+
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(projectLocationLabel)
+ .addComponent(projectLocationTextField,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(browseButton))
+
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(createdFolderLabel)
+ .addComponent(createdFolderTextField,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(213, Short.MAX_VALUE))
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ private void browseButtonActionPerformed(java.awt.event.ActionEvent evt)
{//GEN-FIRST:event_browseButtonActionPerformed
+ String command = evt.getActionCommand();
+ if ("BROWSE".equals(command)) {
+ JFileChooser chooser = new JFileChooser();
+ FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
+ chooser.setDialogTitle("Select Project Location");
+ chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ String path = this.projectLocationTextField.getText();
+ if (path.length() > 0) {
+ File f = new File(path);
+ if (f.exists()) {
+ chooser.setSelectedFile(f);
+ }
+ }
+ if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) {
+ File projectDir = chooser.getSelectedFile();
+
projectLocationTextField.setText(FileUtil.normalizeFile(projectDir).getAbsolutePath());
+ }
+ panel.fireChangeEvent();
+ }
+
+ }//GEN-LAST:event_browseButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton browseButton;
+ private javax.swing.JLabel createdFolderLabel;
+ private javax.swing.JTextField createdFolderTextField;
+ private javax.swing.JLabel projectLocationLabel;
+ private javax.swing.JTextField projectLocationTextField;
+ private javax.swing.JLabel projectNameLabel;
+ private javax.swing.JTextField projectNameTextField;
+ // End of variables declaration//GEN-END:variables
+
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ //same problem as in 31086, initial focus on Cancel button
+ projectNameTextField.requestFocus();
+ }
+
+ boolean valid(WizardDescriptor wizardDescriptor) {
+
+ if (projectNameTextField.getText().length() == 0) {
+ // TODO if using org.openide.dialogs >= 7.8, can use
WizardDescriptor.PROP_ERROR_MESSAGE:
+ wizardDescriptor.putProperty("WizardPanel_errorMessage",
+ "Project Name is not a valid folder name.");
+ return false; // Display name not specified
+ }
+ File f = FileUtil.normalizeFile(new
File(projectLocationTextField.getText()).getAbsoluteFile());
+ if (!f.isDirectory()) {
+ String message = "Project Folder is not a valid path.";
+ wizardDescriptor.putProperty("WizardPanel_errorMessage", message);
+ return false;
+ }
+ final File destFolder = FileUtil.normalizeFile(new
File(createdFolderTextField.getText()).getAbsoluteFile());
+
+ File projLoc = destFolder;
+ while (projLoc != null && !projLoc.exists()) {
+ projLoc = projLoc.getParentFile();
+ }
+ if (projLoc == null || !projLoc.canWrite()) {
+ wizardDescriptor.putProperty("WizardPanel_errorMessage",
+ "Project Folder cannot be created.");
+ return false;
+ }
+
+ if (FileUtil.toFileObject(projLoc) == null) {
+ String message = "Project Folder is not a valid path.";
+ wizardDescriptor.putProperty("WizardPanel_errorMessage", message);
+ return false;
+ }
+
+ File[] kids = destFolder.listFiles();
+ if (destFolder.exists() && kids != null && kids.length > 0) {
+ // Folder exists and is not empty
+ wizardDescriptor.putProperty("WizardPanel_errorMessage",
+ "Project Folder already exists and is not empty.");
+ return false;
+ }
+ wizardDescriptor.putProperty("WizardPanel_errorMessage", "");
+ return true;
+ }
+
+ void store(WizardDescriptor d) {
+ String name = projectNameTextField.getText().trim();
+ String folder = createdFolderTextField.getText().trim();
+
+ d.putProperty("projdir", new File(folder));
+ d.putProperty("name", name);
+ }
+
+ void read(WizardDescriptor settings) {
+ File projectLocation = (File) settings.getProperty("projdir");
+ if (projectLocation == null || projectLocation.getParentFile() == null
|| !projectLocation.getParentFile().isDirectory()) {
+ projectLocation = ProjectChooser.getProjectsFolder();
+ } else {
+ projectLocation = projectLocation.getParentFile();
+ }
+
this.projectLocationTextField.setText(projectLocation.getAbsolutePath());
+
+ String projectName = (String) settings.getProperty("name");
+ if (projectName == null) {
+ projectName = "Plc4xProject";
+ }
+ this.projectNameTextField.setText(projectName);
+ this.projectNameTextField.selectAll();
+ }
+
+ void validate(WizardDescriptor d) throws WizardValidationException {
+ // nothing to validate
+ }
+
+ // Implementation of DocumentListener
--------------------------------------
+ public void changedUpdate(DocumentEvent e) {
+ updateTexts(e);
+ if (this.projectNameTextField.getDocument() == e.getDocument()) {
+ firePropertyChange(PROP_PROJECT_NAME, null,
this.projectNameTextField.getText());
+ }
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ updateTexts(e);
+ if (this.projectNameTextField.getDocument() == e.getDocument()) {
+ firePropertyChange(PROP_PROJECT_NAME, null,
this.projectNameTextField.getText());
+ }
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ updateTexts(e);
+ if (this.projectNameTextField.getDocument() == e.getDocument()) {
+ firePropertyChange(PROP_PROJECT_NAME, null,
this.projectNameTextField.getText());
+ }
+ }
+
+ /**
+ * Handles changes in the Project name and project directory,
+ */
+ private void updateTexts(DocumentEvent e) {
+
+ Document doc = e.getDocument();
+
+ if (doc == projectNameTextField.getDocument() || doc ==
projectLocationTextField.getDocument()) {
+ // Change in the project name
+
+ String projectName = projectNameTextField.getText();
+ String projectFolder = projectLocationTextField.getText();
+
+ //if (projectFolder.trim().length() == 0 ||
projectFolder.equals(oldName)) {
+ createdFolderTextField.setText(projectFolder + File.separatorChar
+ projectName);
+ //}
+
+ }
+ panel.fireChangeEvent(); // Notify that the panel changed
+ }
+
+}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardIterator.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardIterator.java
new file mode 100644
index 0000000..e7f80b8
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardIterator.java
@@ -0,0 +1,240 @@
+/*
+ * 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
+ *
+ * https://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.apache.plc4x.malbec.projecttype.core;
+
+import java.awt.Component;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import javax.swing.JComponent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.templates.TemplateRegistration;
+import org.netbeans.spi.project.ui.support.ProjectChooser;
+import org.netbeans.spi.project.ui.templates.support.Templates;
+import org.openide.WizardDescriptor;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.NbBundle.Messages;
+import org.openide.xml.XMLUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+// TODO define position attribute
+@TemplateRegistration(folder = "Project/Samples", displayName =
"#Plc4xProject_displayName", description = "Plc4xProjectDescription.html",
iconBase = "org/apache/plc4x/malbec/projecttype/core/Plc4xProject.png", content
= "Plc4xProjectProject.zip")
+@Messages("Plc4xProject_displayName=Plc4xProject")
+public class Plc4xProjectWizardIterator implements
WizardDescriptor./*Progress*/InstantiatingIterator {
+
+ private int index;
+ private WizardDescriptor.Panel[] panels;
+ private WizardDescriptor wiz;
+
+ public Plc4xProjectWizardIterator() {
+ }
+
+ public static Plc4xProjectWizardIterator createIterator() {
+ return new Plc4xProjectWizardIterator();
+ }
+
+ private WizardDescriptor.Panel[] createPanels() {
+ return new WizardDescriptor.Panel[]{
+ new Plc4xProjectWizardPanel(),};
+ }
+
+ private String[] createSteps() {
+ return new String[]{
+ NbBundle.getMessage(Plc4xProjectWizardIterator.class,
"LBL_CreateProjectStep")
+ };
+ }
+
+ public Set/*<FileObject>*/ instantiate(/*ProgressHandle handle*/) throws
IOException {
+ Set<FileObject> resultSet = new LinkedHashSet<FileObject>();
+ File dirF = FileUtil.normalizeFile((File) wiz.getProperty("projdir"));
+ dirF.mkdirs();
+
+ FileObject template = Templates.getTemplate(wiz);
+ FileObject dir = FileUtil.toFileObject(dirF);
+ unZipFile(template.getInputStream(), dir);
+
+ // Always open top dir as a project:
+ resultSet.add(dir);
+ // Look for nested projects to open as well:
+ Enumeration<? extends FileObject> e = dir.getFolders(true);
+ while (e.hasMoreElements()) {
+ FileObject subfolder = e.nextElement();
+ if (ProjectManager.getDefault().isProject(subfolder)) {
+ resultSet.add(subfolder);
+ }
+ }
+
+ File parent = dirF.getParentFile();
+ if (parent != null && parent.exists()) {
+ ProjectChooser.setProjectsFolder(parent);
+ }
+
+ return resultSet;
+ }
+
+ public void initialize(WizardDescriptor wiz) {
+ this.wiz = wiz;
+ index = 0;
+ panels = createPanels();
+ // Make sure list of steps is accurate.
+ String[] steps = createSteps();
+ for (int i = 0; i < panels.length; i++) {
+ Component c = panels[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;
+ // Step #.
+ // TODO if using org.openide.dialogs >= 7.8, can use
WizardDescriptor.PROP_*:
+ jc.putClientProperty("WizardPanel_contentSelectedIndex", i);
+ // Step name (actually the whole list for reference).
+ jc.putClientProperty("WizardPanel_contentData", steps);
+ }
+ }
+ }
+
+ public void uninitialize(WizardDescriptor wiz) {
+ this.wiz.putProperty("projdir", null);
+ this.wiz.putProperty("name", null);
+ this.wiz = null;
+ panels = null;
+ }
+
+ public String name() {
+ return MessageFormat.format("{0} of {1}",
+ new Object[]{index + 1, panels.length});
+ }
+
+ public boolean hasNext() {
+ return index < panels.length - 1;
+ }
+
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ public void nextPanel() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ index++;
+ }
+
+ public void previousPanel() {
+ if (!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ index--;
+ }
+
+ public WizardDescriptor.Panel current() {
+ return panels[index];
+ }
+
+ // If nothing unusual changes in the middle of the wizard, simply:
+ public final void addChangeListener(ChangeListener l) {
+ }
+
+ public final void removeChangeListener(ChangeListener l) {
+ }
+
+ private static void unZipFile(InputStream source, FileObject projectRoot)
throws IOException {
+ try {
+ ZipInputStream str = new ZipInputStream(source);
+ ZipEntry entry;
+ while ((entry = str.getNextEntry()) != null) {
+ if (entry.isDirectory()) {
+ FileUtil.createFolder(projectRoot, entry.getName());
+ } else {
+ FileObject fo = FileUtil.createData(projectRoot,
entry.getName());
+ if ("nbproject/project.xml".equals(entry.getName())) {
+ // Special handling for setting name of Ant-based
projects; customize as needed:
+ filterProjectXML(fo, str, projectRoot.getName());
+ } else {
+ writeFile(str, fo);
+ }
+ }
+ }
+ } finally {
+ source.close();
+ }
+ }
+
+ private static void writeFile(ZipInputStream str, FileObject fo) throws
IOException {
+ OutputStream out = fo.getOutputStream();
+ try {
+ FileUtil.copy(str, out);
+ } finally {
+ out.close();
+ }
+ }
+
+ private static void filterProjectXML(FileObject fo, ZipInputStream str,
String name) throws IOException {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ FileUtil.copy(str, baos);
+ Document doc = XMLUtil.parse(new InputSource(new
ByteArrayInputStream(baos.toByteArray())), false, false, null, null);
+ NodeList nl =
doc.getDocumentElement().getElementsByTagName("name");
+ if (nl != null) {
+ for (int i = 0; i < nl.getLength(); i++) {
+ Element el = (Element) nl.item(i);
+ if (el.getParentNode() != null &&
"data".equals(el.getParentNode().getNodeName())) {
+ NodeList nl2 = el.getChildNodes();
+ if (nl2.getLength() > 0) {
+ nl2.item(0).setNodeValue(name);
+ }
+ break;
+ }
+ }
+ }
+ OutputStream out = fo.getOutputStream();
+ try {
+ XMLUtil.write(doc, out, "UTF-8");
+ } finally {
+ out.close();
+ }
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ writeFile(str, fo);
+ }
+
+ }
+
+}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardPanel.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardPanel.java
new file mode 100644
index 0000000..7dc4f0a
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectWizardPanel.java
@@ -0,0 +1,104 @@
+/*
+ * 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
+ *
+ * https://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.apache.plc4x.malbec.projecttype.core;
+
+import java.awt.Component;
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.WizardValidationException;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+
+/**
+ * Panel just asking for basic info.
+ */
+public class Plc4xProjectWizardPanel implements WizardDescriptor.Panel,
+ WizardDescriptor.ValidatingPanel, WizardDescriptor.FinishablePanel {
+
+ private WizardDescriptor wizardDescriptor;
+ private Plc4xProjectPanelVisual component;
+
+ public Plc4xProjectWizardPanel() {
+ }
+
+ public Component getComponent() {
+ if (component == null) {
+ component = new Plc4xProjectPanelVisual(this);
+
component.setName(NbBundle.getMessage(Plc4xProjectWizardPanel.class,
"LBL_CreateProjectStep"));
+ }
+ return component;
+ }
+
+ public HelpCtx getHelp() {
+ return new HelpCtx(Plc4xProjectWizardPanel.class);
+ }
+
+ public boolean isValid() {
+ getComponent();
+ return component.valid(wizardDescriptor);
+ }
+
+ private final Set<ChangeListener> listeners = new
HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
+
+ public final void addChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.add(l);
+ }
+ }
+
+ public final void removeChangeListener(ChangeListener l) {
+ synchronized (listeners) {
+ listeners.remove(l);
+ }
+ }
+
+ protected final void fireChangeEvent() {
+ Set<ChangeListener> ls;
+ synchronized (listeners) {
+ ls = new HashSet<ChangeListener>(listeners);
+ }
+ ChangeEvent ev = new ChangeEvent(this);
+ for (ChangeListener l : ls) {
+ l.stateChanged(ev);
+ }
+ }
+
+ public void readSettings(Object settings) {
+ wizardDescriptor = (WizardDescriptor) settings;
+ component.read(wizardDescriptor);
+ }
+
+ public void storeSettings(Object settings) {
+ WizardDescriptor d = (WizardDescriptor) settings;
+ component.store(d);
+ }
+
+ public boolean isFinishPanel() {
+ return true;
+ }
+
+ public void validate() throws WizardValidationException {
+ getComponent();
+ component.validate(wizardDescriptor);
+ }
+
+}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xCustomizerProviderImpl.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xCustomizerProviderImpl.java
new file mode 100644
index 0000000..e1ae926
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xCustomizerProviderImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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
+ *
+ * https://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.apache.plc4x.malbec.projecttype.impl;
+
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.spi.project.ui.CustomizerProvider2;
+import org.netbeans.spi.project.ui.support.ProjectCustomizer;
+import org.openide.awt.StatusDisplayer;
+import org.openide.util.lookup.Lookups;
+
+public class Plc4xCustomizerProviderImpl implements CustomizerProvider2 {
+
+ public final Plc4xProjectImpl project;
+
+ public static final String CUSTOMIZER_FOLDER_PATH =
+ "Projects/org-plc4x-project/Customizer";
+
+ public Plc4xCustomizerProviderImpl(Plc4xProjectImpl project) {
+ this.project = null;
+ }
+
+ @Override
+ public void showCustomizer(String string, String string1) {
+ //
+ }
+
+ @Override
+ public void showCustomizer() {
+ Dialog dialog = ProjectCustomizer.createCustomizerDialog(
+ //Path to layer folder:
+ CUSTOMIZER_FOLDER_PATH,
+ //Lookup, which must contain, at least, the Project:
+ Lookups.fixed(project),
+ //Preselected category:
+ "",
+ //OK button listener:
+ new OKOptionListener(),
+ //HelpCtx for Help button of dialog:
+ null);
+ dialog.setTitle(ProjectUtils.getInformation(project).getDisplayName());
+ dialog.setVisible(true);
+ }
+
+ private class OKOptionListener implements ActionListener {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StatusDisplayer.getDefault().setStatusText("OK button clicked for "
+ + project.getProjectDirectory().getName() + "
customizer!");
+ }
+
+ }
+
+}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectImpl.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectImpl.java
index 3a42a7c..1d8ad32 100644
---
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectImpl.java
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectImpl.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.malbec.projecttype.impl;
import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.ImageIcon;
+import org.apache.plc4x.malbec.projecttype.panels.Plc4xGeneralPropertiesImpl;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
@@ -52,8 +53,11 @@ public class Plc4xProjectImpl implements Project{
if (lkp == null) {
lkp = Lookups.fixed(new Object[]{
// register your features here
+ this,
new Plc4xProjectInfoImpl(),
new Plc4xProjectLogicalViewImpl(this),
+ new Plc4xCustomizerProviderImpl(this),
+ new Plc4xGeneralPropertiesImpl()
});
}
return lkp;
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectLogicalViewImpl.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectLogicalViewImpl.java
index 18cb69a..40456ca 100644
---
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectLogicalViewImpl.java
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/impl/Plc4xProjectLogicalViewImpl.java
@@ -23,6 +23,7 @@ import javax.swing.Action;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.spi.project.ui.LogicalViewProvider;
import org.netbeans.spi.project.ui.support.CommonProjectActions;
+import org.netbeans.spi.project.ui.support.NodeFactorySupport;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObjectNotFoundException;
@@ -79,12 +80,14 @@ public class Plc4xProjectLogicalViewImpl implements
LogicalViewProvider {
public ProjectNode(Node node, Plc4xProjectImpl project)
throws DataObjectNotFoundException {
super(node,
- new FilterNode.Children(node),
- new ProxyLookup(
- new Lookup[]{
- Lookups.singleton(project),
- node.getLookup()
- }));
+ NodeFactorySupport.createCompositeChildren(project,
+ "Projects/org-plc4x-project/Nodes"),
+// new FilterNode.Children(node),
+ new ProxyLookup(
+ new Lookup[]{
+ Lookups.singleton(project),
+ node.getLookup()
+ }));
this.project = project;
}
@@ -94,7 +97,8 @@ public class Plc4xProjectLogicalViewImpl implements
LogicalViewProvider {
CommonProjectActions.newFileAction(),
CommonProjectActions.copyProjectAction(),
CommonProjectActions.deleteProjectAction(),
- CommonProjectActions.closeProjectAction()
+ CommonProjectActions.closeProjectAction(),
+ CommonProjectActions.customizeProjectAction()
};
}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/nodes/TextsNodeFactory.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/nodes/TextsNodeFactory.java
new file mode 100644
index 0000000..3cabd99
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/nodes/TextsNodeFactory.java
@@ -0,0 +1,102 @@
+/*
+ * 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
+ *
+ * https://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.apache.plc4x.malbec.projecttype.nodes;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.event.ChangeListener;
+import org.apache.plc4x.malbec.projecttype.impl.Plc4xProjectImpl;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ui.support.NodeFactory;
+import org.netbeans.spi.project.ui.support.NodeList;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.nodes.FilterNode;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+
[email protected](projectType = "org-plc4x-project", position = 10)
+public class TextsNodeFactory implements NodeFactory {
+
+ @Override
+ public NodeList<?> createNodes(Project prjct) {
+ Plc4xProjectImpl p = prjct.getLookup().lookup(Plc4xProjectImpl.class);
+ assert p != null;
+ return new TextsNodeList(p);
+ }
+
+ private class TextsNodeList implements NodeList<Node> {
+
+ Plc4xProjectImpl project;
+
+ public TextsNodeList(Plc4xProjectImpl project) {
+ this.project = project;
+ }
+
+ @Override
+ public List<Node> keys() {
+ FileObject textsFolder =
+ project.getProjectDirectory().getFileObject("texts");
+ try {
+ System.out.println(">> " + textsFolder.asText());
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ List<Node> result = new ArrayList<Node>();
+ if (textsFolder != null) {
+ for (FileObject textsFolderFile : textsFolder.getChildren()) {
+ try {
+ System.out.println("> " + textsFolderFile.asText());
+
result.add(DataObject.find(textsFolderFile).getNodeDelegate());
+ } catch (DataObjectNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Node node(Node node) {
+ return new FilterNode(node);
+ }
+
+ @Override
+ public void addNotify() {
+ }
+
+ @Override
+ public void removeNotify() {
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener cl) {
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener cl) {
+ }
+
+ }
+
+}
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/panels/Plc4xGeneralPropertiesImpl.java
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/panels/Plc4xGeneralPropertiesImpl.java
new file mode 100644
index 0000000..558be2b
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/java/org/apache/plc4x/malbec/projecttype/panels/Plc4xGeneralPropertiesImpl.java
@@ -0,0 +1,51 @@
+/*
+ * 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
+ *
+ * https://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.apache.plc4x.malbec.projecttype.panels;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import org.netbeans.spi.project.ui.support.ProjectCustomizer;
+import org.netbeans.spi.project.ui.support.ProjectCustomizer.Category;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+
+public class Plc4xGeneralPropertiesImpl implements
ProjectCustomizer.CompositeCategoryProvider {
+
+ private static final String GENERAL = "General";
+
+ @ProjectCustomizer.CompositeCategoryProvider.Registration(projectType =
"org-customer-project", position = 10)
+ public static Plc4xGeneralPropertiesImpl createGeneral() {
+ return new Plc4xGeneralPropertiesImpl();
+ }
+
+ @NbBundle.Messages("LBL_Config_General=General")
+ @Override
+ public Category createCategory(Lookup lkp) {
+ return ProjectCustomizer.Category.create(
+ GENERAL,
+ Bundle.LBL_Config_General(),
+ null);
+ }
+
+ @Override
+ public JComponent createComponent(Category category, Lookup lkp) {
+ return new JPanel();
+ }
+
+}
\ No newline at end of file
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Bundle.properties
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Bundle.properties
new file mode 100644
index 0000000..03bad77
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Bundle.properties
@@ -0,0 +1,6 @@
+LBL_CreateProjectStep=Name and Location
+Plc4xProjectPanelVisual.projectNameLabel.text=Project &Name:
+Plc4xProjectPanelVisual.createdFolderLabel.text=Project &Folder:
+Plc4xProjectPanelVisual.browseButton.actionCommand=BROWSE
+Plc4xProjectPanelVisual.browseButton.text=Br&owse...
+Plc4xProjectPanelVisual.projectLocationLabel.text=Project &Location:
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProject.png
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProject.png
new file mode 100644
index 0000000..8b16129
Binary files /dev/null and
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProject.png
differ
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectDescription.html
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectDescription.html
new file mode 100644
index 0000000..7422bcc
--- /dev/null
+++
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectDescription.html
@@ -0,0 +1,12 @@
+<!--
+Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to
change this license
+Click
nbfs://nbhost/SystemFileSystem/Templates/NetBeansModuleDevelopment-files/templateDescription.html
to edit this template
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Sample Plc4xProject project
+ </body>
+</html>
diff --git
a/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectProject.zip
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectProject.zip
new file mode 100644
index 0000000..caae736
Binary files /dev/null and
b/plc4j/tools/malbec/malbec-projecttype/src/main/resources/org/apache/plc4x/malbec/projecttype/core/Plc4xProjectProject.zip
differ