Commits

Anonymous committed 2b95317

Initial version - lexers work, including embedding.

Comments (0)

Files changed (22)

+\.orig$
+\.orig\..*$
+\.chg\..*$
+\.rej$
+\.conflict\~$
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="org.netbeans.examples.props" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project org.netbeans.examples.props.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.examples.props
+OpenIDE-Module-Layer: org/netbeans/examples/props/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/netbeans/examples/props/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+

nbproject/build-impl.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="org.netbeans.examples.props-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/platform-private.properties"/>
+    <property file="nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>

nbproject/genfiles.properties

+build.xml.data.CRC32=d247cae2
+build.xml.script.CRC32=277de3aa
+build.xml.stylesheet.CRC32=a56c6a5b@2.46.1
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=d247cae2
+nbproject/build-impl.xml.script.CRC32=8e6af56d
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.46.1

nbproject/platform.properties

+cluster.path=\
+    ${nbplatform.active.dir}/nb:\
+    ${nbplatform.active.dir}/enterprise:\
+    ${nbplatform.active.dir}/ide:\
+    ${nbplatform.active.dir}/java:\
+    ${nbplatform.active.dir}/dlight:\
+    ${nbplatform.active.dir}/websvccommon:\
+    ${nbplatform.active.dir}/apisupport:\
+    ${nbplatform.active.dir}/profiler:\
+    ${nbplatform.active.dir}/platform:\
+    ${nbplatform.active.dir}/cnd:\
+    ${nbplatform.active.dir}/harness
+nbplatform.active=default

nbproject/project.properties

+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint:-serial

nbproject/project.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.examples.props</code-name-base>
+            <standalone/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.core.multiview</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.25.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.23.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.41.1.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.38.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.52.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.31.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.24.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.text</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.41.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.17.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.10.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.45.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>

src/org/netbeans/examples/props/Bundle.properties

+OpenIDE-Module-Name=Props Example
+Services/MIMEResolver/PropsResolver.xml=Props Files
+Templates/Other/PropsTemplate.props=Empty Props file

src/org/netbeans/examples/props/PropsResolver.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+To change this template, choose Tools | Templates
+and open the template in the editor.
+-->
+<!DOCTYPE MIME-resolver PUBLIC "-//NetBeans//DTD MIME Resolver 1.0//EN" "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">
+<MIME-resolver>
+    <file>
+        <ext name="props"/>
+        <resolver mime="text/x-props"/>
+    </file>
+</MIME-resolver>

src/org/netbeans/examples/props/PropsTemplate.props

Empty file added.

src/org/netbeans/examples/props/api/ExpressionTokenId.java

+package org.netbeans.examples.props.api;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.examples.props.lexer.ExpressionLexer;
+import org.netbeans.examples.props.lexer.PropsLexer;
+import org.netbeans.spi.lexer.LanguageHierarchy;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+
+public enum ExpressionTokenId implements TokenId {
+    
+    NUMBER("number"),
+    OPERATOR("operator"),
+    WHITESPACE("whitespace"),
+    ERROR("error");
+    
+    private final String category;
+
+    private ExpressionTokenId(String category) {
+        this.category = category;
+    }
+
+    @Override
+    public String primaryCategory() {
+        return category;
+    }
+    
+    private static final Language<ExpressionTokenId> language = new LanguageHierarchy<ExpressionTokenId>() {
+        @Override
+        protected Collection<ExpressionTokenId> createTokenIds() {
+            return Arrays.asList(ExpressionTokenId.values());
+        }
+
+        @Override
+        protected Lexer<ExpressionTokenId> createLexer(LexerRestartInfo<ExpressionTokenId> info) {
+            return new ExpressionLexer(info);
+        }
+
+        @Override
+        protected String mimeType() {
+            return "text/x-expression";
+        }
+
+    }.language();
+
+    @MimeRegistration(mimeType="text/x-expression", service=Language.class)
+    public static Language<ExpressionTokenId> language() {
+        return language;
+    }
+    
+}

src/org/netbeans/examples/props/api/PropsTokenId.java

+/*
+ * To change this template, choose Tools | Templates and open the template in
+ * the editor.
+ */
+package org.netbeans.examples.props.api;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.lexer.InputAttributes;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.api.lexer.LanguagePath;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenId;
+import org.netbeans.examples.props.lexer.PropsLexer;
+import org.netbeans.spi.lexer.LanguageEmbedding;
+import org.netbeans.spi.lexer.LanguageHierarchy;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+
+/**
+ *
+ * @author lahvac
+ */
+public enum PropsTokenId implements TokenId {
+
+    KEY("key"),
+    STRING_VALUE("value"),
+    EXPRESSION("value"),
+    ASSIGN("operator"),
+    NEW_LINE("whitespace");
+    
+    private final String category;
+
+    private PropsTokenId(String category) {
+        this.category = category;
+    }
+    
+    @Override
+    public String primaryCategory() {
+        return category;
+    }
+    
+    private static final Language<PropsTokenId> language = new LanguageHierarchy<PropsTokenId>() {
+        @Override
+        protected Collection<PropsTokenId> createTokenIds() {
+            return Arrays.asList(PropsTokenId.values());
+        }
+
+        @Override
+        protected Lexer<PropsTokenId> createLexer(LexerRestartInfo<PropsTokenId> info) {
+            return new PropsLexer(info);
+        }
+
+        @Override
+        protected String mimeType() {
+            return "text/x-props";
+        }
+
+        @Override
+        protected LanguageEmbedding<?> embedding(Token<PropsTokenId> token, LanguagePath languagePath, InputAttributes inputAttributes) {
+            switch (token.id()) {
+                case EXPRESSION:
+                    return LanguageEmbedding.create(Language.find("text/x-expression"), 3, 2);
+                default:
+                    return null;
+            }
+        }
+
+    }.language();
+
+    @MimeRegistration(mimeType="text/x-props", service=Language.class)
+    public static Language<PropsTokenId> language() {
+        return language;
+    }
+}

src/org/netbeans/examples/props/fontsColors.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE fontscolors PUBLIC "-//NetBeans//DTD Editor Fonts and Colors settings 1.1//EN" "http://www.netbeans.org/dtds/EditorFontsColors-1_1.dtd">
+
+<fontscolors>
+    
+    <fontcolor name="key" foreColor="blue">
+        <font style="bold" />
+    </fontcolor>
+    
+    <fontcolor name="value" default="identifier" />
+    
+</fontscolors>

src/org/netbeans/examples/props/layer.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+    <folder name="Loaders">
+        <folder name="text">
+            <folder name="x-props">
+                <folder name="Actions">
+                    <file name="org-openide-actions-CopyAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CopyAction.instance"/>
+                        <attr name="position" intvalue="400"/>
+                    </file>
+                    <file name="org-openide-actions-CutAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-CutAction.instance"/>
+                        <attr name="position" intvalue="300"/>
+                    </file>
+                    <file name="org-openide-actions-DeleteAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/Edit/org-openide-actions-DeleteAction.instance"/>
+                        <attr name="position" intvalue="600"/>
+                    </file>
+                    <file name="org-openide-actions-FileSystemAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-FileSystemAction.instance"/>
+                        <attr name="position" intvalue="1100"/>
+                    </file>
+                    <file name="org-openide-actions-OpenAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-OpenAction.instance"/>
+                        <attr name="position" intvalue="100"/>
+                    </file>
+                    <file name="org-openide-actions-PropertiesAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-PropertiesAction.instance"/>
+                        <attr name="position" intvalue="1400"/>
+                    </file>
+                    <file name="org-openide-actions-RenameAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-RenameAction.instance"/>
+                        <attr name="position" intvalue="700"/>
+                    </file>
+                    <file name="org-openide-actions-SaveAsTemplateAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-SaveAsTemplateAction.instance"/>
+                        <attr name="position" intvalue="900"/>
+                    </file>
+                    <file name="org-openide-actions-ToolsAction.shadow">
+                        <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-ToolsAction.instance"/>
+                        <attr name="position" intvalue="1300"/>
+                    </file>
+                    <file name="sep-1.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="200"/>
+                    </file>
+                    <file name="sep-2.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="500"/>
+                    </file>
+                    <file name="sep-3.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="800"/>
+                    </file>
+                    <file name="sep-4.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="1000"/>
+                    </file>
+                    <file name="sep-5.instance">
+                        <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
+                        <attr name="position" intvalue="1200"/>
+                    </file>
+                </folder>
+                <folder name="Factories">
+                    <file name="PropsDataLoader.instance">
+                        <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/netbeans/examples/props/loader/props.png"/>
+                        <attr name="dataObjectClass" stringvalue="org.netbeans.examples.props.loader.PropsDataObject"/>
+                        <attr name="instanceCreate" methodvalue="org.openide.loaders.DataLoaderPool.factory"/>
+                        <attr name="mimeType" stringvalue="text/x-props"/>
+                    </file>
+                </folder>
+            </folder>
+        </folder>
+    </folder>
+    <folder name="Services">
+        <folder name="MIMEResolver">
+            <file name="PropsResolver.xml" url="PropsResolver.xml">
+                <attr name="displayName" bundlevalue="org.netbeans.examples.props.Bundle#Services/MIMEResolver/PropsResolver.xml"/>
+            </file>
+        </folder>
+    </folder>
+    <folder name="Templates">
+        <folder name="Other">
+            <file name="PropsTemplate.props" url="PropsTemplate.props">
+                <attr name="displayName" bundlevalue="org.netbeans.examples.props.Bundle#Templates/Other/PropsTemplate.props"/>
+                <attr name="template" boolvalue="true"/>
+            </file>
+        </folder>
+    </folder>
+
+    <folder name="Editors">
+        <folder name="text">
+            <folder name="x-props">
+<!--                <file name="language.instance">
+                    <attr name="instanceCreate" methodvalue="org.netbeans.modules.java.hints.declarative.DeclarativeHintTokenId.language"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.api.lexer.Language"/>
+                </file>-->
+                <folder name="FontsColors">
+                    <folder name="NetBeans">
+                        <folder name="Defaults">
+                            <file name="org-netbeans-examples-props-token-colorings.xml" url="fontsColors.xml">
+                            </file>
+                        </folder>
+                    </folder>
+                </folder>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>

src/org/netbeans/examples/props/lexer/ExpressionLexer.java

+package org.netbeans.examples.props.lexer;
+
+import org.netbeans.api.lexer.Token;
+import org.netbeans.examples.props.api.ExpressionTokenId;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerInput;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+import org.netbeans.spi.lexer.TokenFactory;
+
+public class ExpressionLexer implements Lexer<ExpressionTokenId> {
+
+    private final LexerInput input;
+    private final TokenFactory<ExpressionTokenId> factory;
+    
+    public ExpressionLexer(LexerRestartInfo<ExpressionTokenId> info) {
+        this.input = info.input();
+        this.factory = info.tokenFactory();
+    }
+
+    @Override
+    public Token<ExpressionTokenId> nextToken() {
+        int read = input.read();
+        
+        if (read == LexerInput.EOF) return null;
+        
+        if (Character.isDigit(read)) {
+            while (Character.isDigit(read = input.read()));
+            
+            if (read != LexerInput.EOF) input.backup(1);
+            
+            return factory.createToken(ExpressionTokenId.NUMBER);
+        }
+        
+        if (read == '+' || read == '-') return factory.createToken(ExpressionTokenId.OPERATOR);
+        
+        if (read == ' ' || read == '\t') return factory.createToken(ExpressionTokenId.WHITESPACE);
+        
+        return factory.createToken(ExpressionTokenId.ERROR);
+    }
+
+    @Override
+    public Object state() {
+        return null;
+    }
+
+    @Override
+    public void release() {}
+    
+}

src/org/netbeans/examples/props/lexer/PropsLexer.java

+package org.netbeans.examples.props.lexer;
+
+import org.netbeans.api.lexer.Token;
+import org.netbeans.examples.props.api.PropsTokenId;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerInput;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+import org.netbeans.spi.lexer.TokenFactory;
+
+public class PropsLexer implements Lexer<PropsTokenId> {
+
+    private final LexerInput input;
+    private final TokenFactory<PropsTokenId> factory;
+    
+    private State expectedNext;
+
+    public PropsLexer(LexerRestartInfo<PropsTokenId> info) {
+        this.input = info.input();
+        this.factory = info.tokenFactory();
+        this.expectedNext = (State) info.state();
+        
+        if (this.expectedNext == null) {
+            this.expectedNext = State.KEY;
+        }
+    }
+
+    @Override
+    public Token<PropsTokenId> nextToken() {
+        int read;
+        
+        switch (expectedNext) {
+            case KEY:
+                while ((read = input.read()) != '=' && read != LexerInput.EOF)
+                    ;
+                
+                if (read == '=') input.backup(1);
+                
+                expectedNext = State.ASSIGN;
+                
+                if (input.readLength() > 0)
+                    return factory.createToken(PropsTokenId.KEY);
+                
+            case ASSIGN:
+                if (input.read() == '=') {
+                    expectedNext = State.VALUE;
+                    return factory.createToken(PropsTokenId.ASSIGN);
+                }
+                
+                return null; //end of the input
+                
+            case VALUE:
+                while ((read = input.read()) != '\n' && read != LexerInput.EOF)
+                    ;
+
+                if (read == '\n') {
+                    input.backup(1);
+                }
+
+                expectedNext = State.NEW_LINE;
+                
+                if (input.readLength() > 0) {
+                    String readText = input.readText().toString();
+
+                    if (readText.startsWith("$((") && readText.endsWith("))"))
+                        return factory.createToken(PropsTokenId.EXPRESSION);
+                    else
+                        return factory.createToken(PropsTokenId.STRING_VALUE);
+                }
+                
+            case NEW_LINE:
+                if (input.read() == '\n') {
+                    expectedNext = State.KEY;
+                    return factory.createToken(PropsTokenId.NEW_LINE);
+                }
+                
+                return null; //end of the input
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public Object state() {
+        return expectedNext;
+    }
+
+    @Override
+    public void release() {}
+    
+    enum State {
+        KEY,
+        ASSIGN,
+        VALUE,
+        NEW_LINE;
+    }
+}

src/org/netbeans/examples/props/loader/Bundle.properties

+LBL_Props_EDITOR=Source

src/org/netbeans/examples/props/loader/PropsDataObject.java

+/*
+ * To change this template, choose Tools | Templates and open the template in
+ * the editor.
+ */
+package org.netbeans.examples.props.loader;
+
+import java.io.IOException;
+import org.netbeans.core.spi.multiview.MultiViewElement;
+import org.netbeans.core.spi.multiview.text.MultiViewEditorElement;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiDataObject;
+import org.openide.loaders.MultiFileLoader;
+import org.openide.util.Lookup;
+import org.openide.windows.TopComponent;
+
+public class PropsDataObject extends MultiDataObject {
+
+    public PropsDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
+        super(pf, loader);
+        registerEditor("text/x-props", true);
+    }
+
+    @Override
+    protected int associateLookup() {
+        return 1;
+    }
+
+    @MultiViewElement.Registration(displayName = "#LBL_Props_EDITOR",
+    iconBase = "org/netbeans/examples/props/loader/props.png",
+    mimeType = "text/x-props",
+    persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED,
+    preferredID = "Props",
+    position = 1000)
+    public static MultiViewEditorElement createEditor(Lookup lkp) {
+        return new MultiViewEditorElement(lkp);
+    }
+}

src/org/netbeans/examples/props/loader/PropsVisualElement.form

+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.8" 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">
+          <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+</Form>

src/org/netbeans/examples/props/loader/PropsVisualElement.java

+/*
+ * To change this template, choose Tools | Templates and open the template in
+ * the editor.
+ */
+package org.netbeans.examples.props.loader;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JToolBar;
+import org.netbeans.core.spi.multiview.CloseOperationState;
+import org.netbeans.core.spi.multiview.MultiViewElement;
+import org.netbeans.core.spi.multiview.MultiViewElementCallback;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+@MultiViewElement.Registration(displayName = "#LBL_Props_VISUAL",
+iconBase = "org/netbeans/examples/props/loader/props.png",
+mimeType = "text/x-props",
+persistenceType = TopComponent.PERSISTENCE_NEVER,
+preferredID = "PropsVisual",
+position = 2000)
+@Messages({
+    "LBL_Props_VISUAL=Visual"
+})
+public final class PropsVisualElement extends JPanel implements MultiViewElement {
+
+    private PropsDataObject obj;
+    private JToolBar toolbar = new JToolBar();
+    private transient MultiViewElementCallback callback;
+
+    public PropsVisualElement(Lookup lkp) {
+        obj = lkp.lookup(PropsDataObject.class);
+        assert obj != null;
+        initComponents();
+    }
+
+    @Override
+    public String getName() {
+        return "PropsVisualElement";
+    }
+
+    /** 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() {
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 400, Short.MAX_VALUE)
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 300, Short.MAX_VALUE)
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    // End of variables declaration//GEN-END:variables
+    @Override
+    public JComponent getVisualRepresentation() {
+        return this;
+    }
+
+    @Override
+    public JComponent getToolbarRepresentation() {
+        return toolbar;
+    }
+
+    @Override
+    public Action[] getActions() {
+        return new Action[0];
+    }
+
+    @Override
+    public Lookup getLookup() {
+        return obj.getLookup();
+    }
+
+    @Override
+    public void componentOpened() {
+    }
+
+    @Override
+    public void componentClosed() {
+    }
+
+    @Override
+    public void componentShowing() {
+    }
+
+    @Override
+    public void componentHidden() {
+    }
+
+    @Override
+    public void componentActivated() {
+    }
+
+    @Override
+    public void componentDeactivated() {
+    }
+
+    @Override
+    public UndoRedo getUndoRedo() {
+        return UndoRedo.NONE;
+    }
+
+    @Override
+    public void setMultiViewCallback(MultiViewElementCallback callback) {
+        this.callback = callback;
+    }
+
+    @Override
+    public CloseOperationState canCloseElement() {
+        return CloseOperationState.STATE_OK;
+    }
+}

src/org/netbeans/examples/props/loader/props.png

Added
New image