diff -r 9387523afe84 editor.lib2/src/org/netbeans/spi/editor/codegen/package.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/editor.lib2/src/org/netbeans/spi/editor/codegen/package.html Wed May 07 13:29:41 2008 +0200
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+ org.netbeans.spi.editor.codegen
+
+
+
+
+ The Code Generator SPI gives modules a chance to plug their own code generators
+ into the popup that appears in the editor on the Insert Code action invocation.
+
+
+
+ Key parts of the SPI
+
+
+ The whole SPI is organized around the
+ CodeGenerator
+ interface, which is the ultimate thing that modules need to implement in order to generate
+ code snippets and insert them into a document on the Insert Code action invocation.
+ The CodeGenerator
s are created by
+ CodeGenerator.Factory
+ instances.
+
+
+
+ Instances of the
+ CodeGeneratorContextProvider
+ interface serve for adding an additonal content to the context which is passed
+ as a parameter to the
+ CodeGenerator.Factory.create
+ method.
+
+
+
+ CodeGenerator and CodeGeneratorContextProvider registration
+
+
+ The registration of CodeGenerator
s has to be done through an
+ instance of the CodeGenerator.Factory
class. The factory should
+ be registered in MimeLookup
under the mime-type of documents, which
+ the CodeGenerator
should be used for, in the CodeGenerators
+ folder. For example, if a module wants to provide CodeGenerator
+ for text/x-something
documents, it should implement its own
+ CodeGenerator.Factory
(e.g. org.some.module.CGFactory
+ class) and register it in MimeLookup
using its XML layer as it is
+ shown on the example below.
+
+
+
+<folder name="Editors">
+ <folder name="text">
+ <folder name="x-something">
+ <folder name="CodeGenerators">
+ <file name="org-some-module-CGFactory.instance" />
+ </folder>
+ </folder>
+ </folder>
+</folder>
+
+
+
+ The CGFactory
class will simply return a new instance of
+ the module's implementation of the CodeGenerator
interface from its
+ create
+ method. The method can create and return multiple CodeGenerator
s.
+
+
+
+ The parameter of the create
method provides by default access to
+ the JTextComponent
, which the generator is being created for. However,
+ a group of factories could exist for a mime-type which require access to
+ an additional data (e.g. some parser result, etc.) when creating their
+ CodeGenerator
s. To that purpose, an instance of
+ CodeGeneratorContextProvider
interface could be created and registered
+ in MimeLookup
under the mime-type in the CodeGeneratorContextProviders
+ folder. For example, if a module wants to provide an additional context for
+ text/x-something
CodeGenerator.Factory
it should
+ implement its own CodeGeneratorContextProvider
+ (e.g. org.some.module.CGContextProvider
class) and register it in
+ MimeLookup
using its XML layer as it is shown on the example below.
+
+
+
+<folder name="Editors">
+ <folder name="text">
+ <folder name="x-something">
+ <folder name="CodeGeneratorContextProviders">
+ <file name="org-some-module-CGContextProvider.instance" />
+ </folder>
+ </folder>
+ </folder>
+</folder>
+
+
+
+ The CGContextProvider
class in its
+ runTaskWithinContext
+ method creates the new context by merging the original context content
+ with the additional data and runs the task obtained as the parameter with the newly
+ created context.
+
+
+
+
diff -r 9387523afe84 editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/editor/src/org/netbeans/modules/editor/codegen/NbGenerateCodeAction.java Wed May 07 13:29:42 2008 +0200
@@ -0,0 +1,184 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.modules.editor.codegen;
+
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.Document;
+import org.netbeans.api.editor.mimelookup.MimePath;
+import org.netbeans.api.lexer.TokenHierarchy;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.editor.*;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.swing.JMenuItem;
+import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.JTextComponent;
+import org.netbeans.api.editor.mimelookup.MimeLookup;
+import org.netbeans.editor.BaseAction;
+import org.netbeans.editor.ext.ExtKit;
+import org.netbeans.spi.editor.codegen.CodeGenerator;
+import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author Dusan Balek, Jan Lahoda
+ */
+public class NbGenerateCodeAction extends BaseAction {
+
+ public static final String generateCode = "generate-code"; //NOI18N
+
+ public NbGenerateCodeAction(){
+ super(generateCode);
+ putValue(ExtKit.TRIMMED_TEXT, NbBundle.getBundle(NbGenerateCodeAction.class).getString("generate-code-trimmed")); //NOI18N
+ putValue(SHORT_DESCRIPTION, NbBundle.getBundle(NbGenerateCodeAction.class).getString("desc-generate-code")); //NOI18N
+ putValue(POPUP_MENU_TEXT, NbBundle.getBundle(NbGenerateCodeAction.class).getString("popup-generate-code")); //NOI18N
+ }
+
+ public void actionPerformed(ActionEvent evt, final JTextComponent target) {
+ Task task = new Task(getFullMimePath(target.getDocument(), target.getCaretPosition()));
+ task.run(Lookups.singleton(target));
+ if (task.codeGenerators.size() > 0) {
+ int altHeight = -1;
+ Point where = null;
+ try {
+ Rectangle carretRectangle = target.modelToView(target.getCaretPosition());
+ altHeight = carretRectangle.height;
+ where = new Point( carretRectangle.x, carretRectangle.y + carretRectangle.height );
+ SwingUtilities.convertPointToScreen(where, target);
+ } catch (BadLocationException ble) {
+ }
+ if (where == null)
+ where = new Point(-1, -1);
+ PopupUtil.showPopup(new GenerateCodePanel(target, task.codeGenerators), null, where.x, where.y, true, altHeight);
+ } else {
+ target.getToolkit().beep();
+ }
+ }
+
+ static String[] test(Document doc, int pos) {
+ Task task = new Task(getFullMimePath(doc, pos));
+ task.run(Lookups.fixed());
+ String[] ret = new String[task.codeGenerators.size()];
+ int i = 0;
+ for (CodeGenerator codeGenerator : task.codeGenerators)
+ ret[i++] = codeGenerator.getDisplayName();
+ return ret;
+ }
+
+ private static MimePath getFullMimePath(Document document, int offset) {
+ String langPath = null;
+
+ if (document instanceof AbstractDocument) {
+ AbstractDocument adoc = (AbstractDocument)document;
+ adoc.readLock();
+ try {
+ List> list = TokenHierarchy.get(document).embeddedTokenSequences(offset, true);
+ if (list.size() > 1) {
+ langPath = list.get(list.size() - 1).languagePath().mimePath();
+ }
+ } finally {
+ adoc.readUnlock();
+ }
+ }
+
+ if (langPath == null) {
+ langPath = NbEditorUtilities.getMimeType(document);
+ }
+
+ if (langPath != null) {
+ return MimePath.parse(langPath);
+ } else {
+ return null;
+ }
+ }
+
+ private static class Task implements CodeGeneratorContextProvider.Task {
+ private MimePath mimePath;
+ private Iterator extends CodeGeneratorContextProvider> contextProviders;
+ private List codeGenerators = new ArrayList();
+
+ private Task(MimePath mimePath) {
+ this.mimePath = mimePath;
+ contextProviders = MimeLookup.getLookup(mimePath).lookupAll(CodeGeneratorContextProvider.class).iterator();
+ }
+
+ public void run(Lookup context) {
+ if (contextProviders.hasNext()) {
+ contextProviders.next().runTaskWithinContext(context, this);
+ } else {
+ for (CodeGenerator.Factory factory : MimeLookup.getLookup(mimePath).lookupAll(CodeGenerator.Factory.class))
+ codeGenerators.addAll(factory.create(context));
+ }
+ }
+ }
+
+ public static final class GlobalAction extends MainMenuAction {
+
+ private final JMenuItem menuPresenter;
+
+ public GlobalAction() {
+ super();
+ this.menuPresenter = new JMenuItem(getMenuItemText());
+ setMenu();
+ }
+
+ protected String getMenuItemText() {
+ return NbBundle.getBundle(GlobalAction.class).getString("generate-code-main-menu-source-item"); //NOI18N
+ }
+
+ protected String getActionName() {
+ return generateCode;
+ }
+
+ public JMenuItem getMenuPresenter() {
+ return menuPresenter;
+ }
+
+ } // End of GlobalAction class
+}
diff -r 9387523afe84 editor/test/unit/src/org/netbeans/modules/editor/codegen/CodeGenerationTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/editor/test/unit/src/org/netbeans/modules/editor/codegen/CodeGenerationTest.java Wed May 07 13:29:42 2008 +0200
@@ -0,0 +1,85 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.modules.editor.codegen;
+
+import javax.swing.text.Document;
+import org.netbeans.modules.editor.*;
+import java.net.URL;
+import javax.swing.text.DefaultStyledDocument;
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Dusan Balek
+ */
+public class CodeGenerationTest extends TestCase {
+
+ public CodeGenerationTest(String testName) {
+ super(testName);
+ }
+
+ // TODO add test methods here. The name must begin with 'test'. For example:
+ // public void testHello() {}
+ protected void setUp() throws Exception {
+ EditorTestLookup.setLookup(
+ new URL[]{EditorTestConstants.EDITOR_LAYER_URL,
+ getClass().getClassLoader().getResource("org/netbeans/modules/editor/resources/codegen-test-layer.xml")
+ },
+ new Object[]{},
+ getClass().getClassLoader());
+ }
+
+ public void testSimpleCodeGenerator() {
+ Document doc = new DefaultStyledDocument();
+ doc.putProperty(NbEditorDocument.MIME_TYPE_PROP, "text/x-simple-codegen-test");
+ String[] generatorNames = NbGenerateCodeAction.test(doc, 0);
+ assertEquals(generatorNames.length, 1);
+ assertEquals(generatorNames[0], "SimpleCodeGenerator");
+ }
+
+ public void testCodeGenerator() {
+ Document doc = new DefaultStyledDocument();
+ doc.putProperty(NbEditorDocument.MIME_TYPE_PROP, "text/x-codegen-test");
+ String[] generatorNames = NbGenerateCodeAction.test(doc, 0);
+ assertEquals(generatorNames.length, 1);
+ assertEquals(generatorNames[0], "CodeGenerator");
+ }
+}
diff -r 9387523afe84 editor/test/unit/src/org/netbeans/modules/editor/codegen/TestCodeGenerator.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/editor/test/unit/src/org/netbeans/modules/editor/codegen/TestCodeGenerator.java Wed May 07 13:29:42 2008 +0200
@@ -0,0 +1,83 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.editor.codegen;
+
+import java.util.Collections;
+import java.util.List;
+import org.netbeans.spi.editor.codegen.CodeGenerator;
+import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+/**
+ *
+ * @author Dusan Balek
+ */
+public class TestCodeGenerator implements CodeGenerator {
+
+ private boolean b;
+
+ public TestCodeGenerator(boolean b) {
+ this.b = b;
+ }
+
+ public String getDisplayName() {
+ return b ? "CodeGenerator" : "SimpleCodeGenerator";
+ }
+
+ public void invoke() {
+ }
+
+ public static class Factory implements CodeGenerator.Factory {
+
+ public List extends CodeGenerator> create(Lookup context) {
+ Object o = context.lookup(ContextProvider.class);
+ return Collections.singletonList(new TestCodeGenerator(o != null));
+ }
+ }
+
+ public static class ContextProvider implements CodeGeneratorContextProvider {
+
+ public void runTaskWithinContext(Lookup context, Task task) {
+ task.run(new ProxyLookup(context, Lookups.singleton(this)));
+ }
+ }
+}
diff -r 9387523afe84 editor/test/unit/src/org/netbeans/modules/editor/resources/codegen-test-layer.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/editor/test/unit/src/org/netbeans/modules/editor/resources/codegen-test-layer.xml Wed May 07 13:29:42 2008 +0200
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+