Source code file content

Revision: 2

import
» Project Revision History

» Checkout URL

web-content / trunk / docs / switch-h-cpp / switch-h-cpp-plugin.html

Size: 20903 bytes, 1 line
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
    <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
    <TITLE>Switch Files plug-in for C/C++ Pack.</TITLE>
    <META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0  (Solaris x86)">
    <META NAME="AUTHOR" CONTENT="Vladimir Voskresensky">
    <META NAME="CREATED" CONTENT="20061204;17571400">
    <META NAME="CHANGEDBY" CONTENT="Vladimir Voskresensky">
    <META NAME="CHANGED" CONTENT="20061204;21232500">
    <STYLE>
        <!--
		H1 { margin-top: 0in; margin-bottom: 0.1in; border: none; padding: 0in; color: #d20106; font-weight: medium; text-align: left }
		P { margin-bottom: 0in; border: none; padding: 0in; color: #2f2f2f; font-family: "Verdana", "Verdana CE", "Arial", "Arial CE", "Lucida Grande CE", "lucida", "Helvetica CE", sans-serif }
		H2 { margin-bottom: 0.05in; border-top: none; border-bottom: 1px solid #d1d1d1; border-left: none; border-right: none; padding-top: 0in; padding-bottom: 0.02in; padding-left: 0in; padding-right: 0in; color: #ee6b00; font-weight: medium; text-align: left }
		H3 { margin-top: 0in; margin-bottom: 0in; border: none; padding: 0in; color: #2d3f8e; font-weight: medium; text-align: left }
		PRE { background: #fff8e4; border: none; padding: 0in; color: #000000; font-family: "Courier New", monospace }
		PRE.examplecode { font-family: "Courier New", monospace }
		A:link { color: #1e2a60; font-weight: medium }
		TT { color: #000000; font-family: "Courier New", monospace }
	-->
    </STYLE>
</HEAD>
<BODY LANG="en-US" TEXT="#2f2f2f" LINK="#1e2a60" DIR="LTR" STYLE="border: none; padding: 0in">
<H1>Extend C/C++ Pack with Switch Source/Header files plug-in</H1>
<P STYLE="margin-bottom: 0.2in">In this tutorial, you will see how
    easy to extend C/C++ Pack base functionality with feature requested
    by community. 
</P>
<P STYLE="margin-bottom: 0.2in">Once this tutorial is finished, you
    will have action for quick switching between associated Source and
    Header files (same name but different suffix). Action name will be
    file-type sensitive, has associated shortcut and be presented by
short name in <TT>Go To </TT>submenu of editor's popup menu.</P>
<P STYLE="margin-bottom: 0.2in"><IMG SRC="goto-header.png" NAME="editor's popup menu" ALIGN=LEFT BORDER=0><BR CLEAR=LEFT><BR><BR>
</P>
<H2><A NAME="gettingtoknowthesample4"></A>Creating test C++ application.</H2>
<P STYLE="margin-bottom: 0.2in">We need test application with source
and header files to test our plug-in. Let's create test C++ Application:</P>
<OL>
<LI><P STYLE="margin-bottom: 0.2in">Choose
    File &gt; New Project. In the New Project wizard, choose <TT>C/C++
    Development </TT>under Categories and <TT>C/C++ Application</TT>
    under Projects. Click Next. Type <TT>SwitchTest</TT> in Project Name
    and set Project Location to an appropriate folder on your disk.
    Uncheck Set as Main Project. Click Finish. 
</P>
<LI><P STYLE="margin-bottom: 0.2in"></A>In
    Project View right click on Header Files to display context menu and
    choose New-&gt;C++ Header File. In Wizard leave File Name as
<TT>newfile</TT>. Click Finish. newfile.h is created.</P>
<LI><P STYLE="margin-bottom: 0.2in">In Project View right click on
    Source Files to display context menu and choose New-&gt;Empty C++
    File. In Wizard leave File Name as <TT>newfile</TT>. Click Finish.
    newfile.cc is created. 
</P>
</OL>
<H2>Creating Netbeans plug-in Module and Action.</H2>
<OL>
    <LI><P STYLE="margin-bottom: 0.2in">Choose File &gt; New Project. In
            the New Project wizard, choose <TT>NetBeans Plug-in Modules</TT>
            under Categories and <TT>Module Project</TT> under Projects. Click
            Next. Type <TT>CppSwitchFiles</TT> in Project Name and set Project
            Location to an appropriate folder on your disk. If they are not
            selected, select Standalone Module and Set as Main Project. Click
            Next. 
        </P>
    </LI>
    <LI><P STYLE="margin-bottom: 0.2in">Type
            <TT>org.netbeans.modules.cppswitchfiles</TT> in Code Name Base.
            Click Finish. 
        </P>
    </LI>
    <LI><P STYLE="margin-bottom: 0.2in">Right-click the module project,
            choose New &gt; File/Folder and choose <TT>Action...</TT> from the
            context menu. 
        </P>
    </LI>
    <LI><P STYLE="margin-bottom: 0.2in">In Wizard choose Action Type as
            <TT>Conditionally Enabled</TT>. Leave selected <TT>User Selects One Node</TT> and Cookie Class as <TT>DataObject</TT>
        </P>
        <P STYLE="margin-bottom: 0.2in">
            <BR CLEAR=LEFT>
            <IMG SRC="ActionType.png" NAME="Action Type" ALIGN=LEFT BORDER=0>
            <BR CLEAR=LEFT>
        </P> 
        <BR CLEAR=LEFT>
    </LI>
    <LI>
        <P STYLE="margin-bottom: 0.2in">
            Click Next and update GUI Registration. Change Category to <TT>Edit </TT>and
            Menu to <TT>Navigate</TT>: 
        </P>
        <P STYLE="margin-bottom: 0.2in">
            <BR CLEAR=LEFT>
            <IMG SRC="ActionGUI.png" NAME="GUI Registration" ALIGN=LEFT BORDER=0>
            <BR CLEAR=LEFT>
        </P>
        <BR CLEAR=LEFT>
    </LI>
    <LI><P STYLE="margin-bottom: 0.2in">Click Next. Change Class Name to
            <TT>CppSwitchAction</TT> and Display Name to <TT>C/C++
            Switch Files</TT>. Click Finish. 
        </P>
    </LI>
    <LI><P STYLE="margin-bottom: 0.2in">Right-click the module project,
            choose Properties, click Display. Change Display Name to <TT>C/C++
        Switch Files </TT>and Display Category to <TT>C/C++.</TT> Click OK.</P>
        <P STYLE="margin-bottom: 0.2in">As result our projects look like:</P>
        <P STYLE="margin-bottom: 0.2in">
            <BR CLEAR=LEFT>
            <IMG SRC="step1_res.png" NAME="result Project view" ALIGN=LEFT BORDER=0>
            <BR CLEAR=LEFT>
        </P>
        <BR CLEAR=LEFT>
    </LI>
</OL>
</PRE><H3 STYLE="margin-bottom: 0.2in">First Review</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the &ldquo;C/C++ Switch
    Files&rdquo; project node and choose <TT>Install/Reload in
    Development IDE</TT>. If a warning message appears, click OK. You can alway uninstall module using <TT>Tools->Module Manager</TT> Category <TT>C/C++</TT>
</P>
<P STYLE="margin-bottom: 0.2in">You can see new menu item in Navigate menu:</P>
<P STYLE="margin-bottom: 0.2in">
    <BR CLEAR=LEFT>
    <IMG SRC="integrate1.png" NAME="Navigate menu" ALIGN=LEFT BORDER=0>
    <BR CLEAR=LEFT>
</P>
<BR CLEAR=LEFT>
<H2><A NAME="DDE_LINK"></A>Implementing Switch Files Action.</H2>
<H3 STYLE="margin-bottom: 0.2in">Add Libraries dependency</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the project, choose
    Properties, click Libraries in the Project Properties dialog box and
    declare a dependency on the following APIs: 
</P>
<OL>
    <LI><P STYLE="margin-bottom: 0.2in"><A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-nodes/overview-summary.html"><FONT COLOR="#3333ff">Nodes
    API</FONT></A></P>
    <LI><P STYLE="margin-bottom: 0.2in"><FONT COLOR="#3333ff">C/C++ Core</FONT></P>
    <LI><P STYLE="margin-bottom: 0.2in"><A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-loaders/overview-summary.html"><FONT COLOR="#3333ff">Datasystems
    API</FONT></A></P>
    <LI><P STYLE="margin-bottom: 0.2in"><A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-filesystems/overview-summary.html"><FONT COLOR="#3333ff">File
    System API</FONT></A></P>
    <LI><P STYLE="margin-bottom: 0.2in"><A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-util/overview-summary.html"><FONT COLOR="#3333ff">Utilites
    API</FONT></A></P>
</OL>
<H3 STYLE="margin-bottom: 0.2in"><A NAME="method1"></A>Configure
enable state of action</H3>
<P STYLE="margin-bottom: 0.2in">Enable action only for Header and
    Source C/C++ files. Change cookieClasses() method (use Alt+Shift+F to
    fix imports): 
</P>
<PRE CLASS="examplecode">        
    protected Class[] cookieClasses() {
        return new Class[] {
                HDataObject.class, CDataObject.class, CCDataObject.class
        };
    }
</PRE><H3 STYLE="margin-bottom: 0.2in">Add utilities to find file where to switch</H3>
<P STYLE="margin-bottom: 0.2in">In activated nodes look for Source or
Header file and find associated Header or Source.</P>
<PRE CLASS="examplecode">    
    private FileObject findToggleFile(final Node[] activatedNodes) {
        FileObject res = null;
        // check whether current file is C++ Source file
        DataObject dob = (CCDataObject) activatedNodes[0].getLookup().lookup(CCDataObject.class);
        if (dob == null) {
            // check whether current file is C Source file
            dob = (CDataObject) activatedNodes[0].getLookup().lookup(CDataObject.class);
        }
        if (dob != null) {
            // it was Source file, find Header
            res = findBrother(dob, getSuffices(HDataLoader.getInstance().getExtensions()));
        } else {
            // check whether current file is Header file
            dob = (HDataObject) activatedNodes[0].getLookup().lookup(HDataObject.class);
            if (dob != null) {
                // try to find C++ Source file
                res = findBrother(dob, getSuffices(CCDataLoader.getInstance().getExtensions()));
                if (res == null) {
                    // try to find C Source file
                    res = findBrother(dob, getSuffices(CDataLoader.getInstance().getExtensions()));
                }
            }
        }
        return res;
    }
    
    private FileObject findBrother(DataObject dob, String[] ext) {
        assert (dob != null);
        assert (dob.getPrimaryFile() != null);
        // get a file object associated with the data object
        FileObject fo = dob.getPrimaryFile();
        if (ext != null &amp;&amp; ext.length &gt; 0) {
            // try to find a file with the same name and one of passed extensions
            for (int i = 0; i &lt; ext.length; i++) {
                // use FileUtilities to find brother of the file object
                FileObject res = FileUtil.findBrother(fo, ext[i]);
                if (res != null) {
                    return res;
                }
            }
        }
        return null;
    }
    
    private static String[] getSuffices(ExtensionList list) {
        List<String> suffixes = new ArrayList<String>();
        for (Enumeration e = list.extensions(); e != null &&  e.hasMoreElements();) {
            String ex = (String) e.nextElement();
            suffixes.add(ex);
        }
        return (String[])suffixes.toArray(new String[suffixes.size()]);
    }    
</PRE><H3 STYLE="margin-bottom: 0.2in">
Implement method to open file in editor</H3>
<PRE CLASS="examplecode">    private void doToggle(final FileObject fo) {
        assert (fo != null);
        try {
            // find a data object for the input file object
            DataObject toggled = DataObject.find(fo);
            if (toggled != null) {
                // check if the data object has possibility to be opened in editor
                final OpenCookie oc = (OpenCookie)toggled.getCookie(OpenCookie.class);
                if (oc != null) {
                    // try to open ASAP, but better not in EQ
                    RequestProcessor.getDefault().post(new Runnable() {
                        public void run() {
                            // open component
                            oc.open();
                        }
                    }, 0, Thread.MAX_PRIORITY);
                }
            }
        } catch (DataObjectNotFoundException ex) {
            // may be error message?
        }
}</PRE><H3 STYLE="margin-bottom: 0.2in">
<A NAME="DDE_LINK3"></A>Implement performAction</H3>
<P STYLE="margin-bottom: 0.2in">Change performAction() method to find
file where to switch:</P>
<PRE CLASS="examplecode"><A NAME="DDE_LINK5"></A>    
    protected void performAction(Node[] activatedNodes) {
        // find file where to switch
        FileObject res = findToggleFile(activatedNodes);
        if (res != null) {
            doToggle(res);
        }
    }

</PRE><H3 STYLE="margin-bottom: 0.2in">
Use Action</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the &ldquo;C/C++ Switch
    Files&rdquo; project node and choose <TT>Install/Reload in
    Development IDE</TT>. Open newfile.cc or newfile.h and try
    Navigate-&gt;C/C++ Switch File menu item. Files will be switched
(opened if necessary).</P>
<H2 STYLE="margin-top: 0in; margin-bottom: 0.2in"><A NAME="DDE_LINK9"></A>
Improve Usability - I</H2>
<P STYLE="margin-bottom: 0.2in">In this part we plan to introduce
    shortcut Ctrl+Shift+A for our action and put it in C/C++ editor context
menu.</P>
<H3 STYLE="margin-bottom: 0.2in">Register shortcut for the Action</H3>
<P STYLE="margin-bottom: 0.2in">Open layer.xml file and add following
on <TT>filesystem</TT> level:</P>
<PRE CLASS="examplecode">&lt;filesystem&gt;
    ...    
    &lt;folder name=&quot;Shortcuts&quot;&gt;
        &lt;file name=&quot;DS-A.shadow&quot;&gt;
            &lt;attr name=&quot;originalFile&quot; stringvalue=&quot;Actions/Edit/org-netbeans-modules-cppswitchfiles-CppSwitchAction.instance&quot;/&gt;
        &lt;/file&gt;
    &lt;/folder&gt; 
    ...
&lt;/filesystem&gt;
<A NAME="DDE_LINK4"></A>  </PRE><H3 STYLE="margin-bottom: 0.2in">
    Register Action in editor context menu 
</H3>
<P STYLE="margin-bottom: 0.2in">Open layer.xml file and add following
on <TT>filesystem</TT> level for C and C++ languages:</P>
<PRE CLASS="examplecode">&lt;filesystem&gt;
    ...    
    &lt;folder name=&quot;Editors&quot;&gt;
        &lt;folder name=&quot;text&quot;&gt;
            &lt;folder name=&quot;x-c++&quot;&gt;
                &lt;folder name=&quot;Popup&quot;&gt;
                    &lt;folder name=&quot;goto&quot;&gt;
                        &lt;file name=&quot;org-netbeans-modules-cppswitchfiles-CppSwitchAction .shadow&quot;&gt;
                            &lt;attr name=&quot;originalFile&quot; stringvalue=&quot;Actions/Edit/org-netbeans-modules-cppswitchfiles-CppSwitchAction.instance&quot;/&gt;
                        &lt;/file&gt;
                    &lt;/folder&gt;
                &lt;/folder&gt;                
            &lt;/folder&gt;
            &lt;folder name=&quot;x-c&quot;&gt;
                &lt;folder name=&quot;Popup&quot;&gt;
                    &lt;folder name=&quot;goto&quot;&gt;
                        &lt;file name=&quot;org-netbeans-modules-cppswitchfiles-CppSwitchAction.shadow&quot;&gt;
                            &lt;attr name=&quot;originalFile&quot; stringvalue=&quot;Actions/Edit/org-netbeans-modules-cppswitchfiles-CppSwitchAction.instance&quot;/&gt;
                        &lt;/file&gt;
                    &lt;/folder&gt;
                &lt;/folder&gt;                
            &lt;/folder&gt;            
        &lt;/folder&gt;
    &lt;/folder&gt;
    ...
<A NAME="DDE_LINK7"></A>&lt;/filesystem&gt;
</PRE><H3 STYLE="margin-bottom: 0.2in">
Use Action</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the &ldquo;C/C++ Switch
    Files&rdquo; project node and choose <TT>Install/Reload in
    Development IDE</TT>. Open newfile.cc or newfile.h and try Ctrl+Shift+A.
Files will be switched. Make sure context menu has added action.</P>
<P STYLE="margin-bottom: 0.2in"><IMG SRC="integrate2.png" NAME="graphics5" ALIGN=LEFT BORDER=0><BR CLEAR=LEFT><BR><BR>
</P>
<H2 STYLE="margin-top: 0in; margin-bottom: 0.2in">Improve Usability -
II</H2>
<P STYLE="margin-bottom: 0.2in">In this part we plan to make our
    action consistent with Netbeans infrastructure and make it file-type
sensitive.</P>
<H3 STYLE="margin-bottom: 0.2in">Add Libraries dependency</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the project, choose
    Properties, click Libraries in the Project Properties dialog box and
    declare a dependency on the <A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-util/overview-summary.html"></A><A HREF="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-editor-lib/overview-summary.html"><FONT COLOR="#3333ff">Editor
Library.</FONT></A><A HREF="http://www.netbeans.org/download/dev/javadoc/org-openide-util/overview-summary.html"></A></P>
<H3 STYLE="margin-bottom: 0.2in">Remember caret positions</H3>
<P STYLE="margin-bottom: 0.2in">To have possibility to go back/forward
between caret positions with Alt+K/Alt+L update doToggle method:</P>
<PRE CLASS="examplecode">    private void doToggle(final FileObject fo) {
       ...
                if (oc != null) {
                    // remember current caret position
                    JTextComponent textComponent = Registry.getMostActiveComponent();
                    JumpList.checkAddEntry(textComponent);
                    // try to open ASAP, but better not in EQ
       ...
}</PRE><H3 STYLE="margin-bottom: 0.2in">
    <BR><BR>
</H3>
<H3 STYLE="margin-bottom: 0.2in">Change Action name to be file type
sensitive</H3>
<P STYLE="margin-bottom: 0.2in">By Netbeans convetions <TT>Go To </TT>submenu uses trimmed
    name for menu items (<TT>Line...</TT> instead of <TT>Go to Line...</TT>) and we will add the same support for our action. 
<BR>
    Also let's make action name to be file type sensitive.
</P>
<P STYLE="margin-bottom: 0.2in">Update Bundle.properties:</P>
<PRE CLASS="examplecode">CTL_CppSwitchAction=C/C++ Switch Files
OpenIDE-Module-Display-Category=C/C++
OpenIDE-Module-Name=C/C++ Switch Files

#names for Navigate menu
CppGoToSourceFileAction=C/C++ Switch to Source File
CppGoToHeaderFileAction=C/C++ Switch to Header File

#short names for Go To popup submenu 
goto-cpp-switch-file=Source/Header File
goto-cpp-source-file=&amp;Source File
goto-cpp-header-file=&amp;Header File</PRE><P STYLE="margin-bottom: 0.2in">
    <BR><BR>
</P>
<H3 STYLE="margin-bottom: 0.2in">Change CppSwitchAction</H3>
<P STYLE="margin-bottom: 0.2in">Add necessary support in
    CppSwitchAction to handle file-type. Update action name in Navigate
menu and editor context submenu to be file-type sensitive:</P>
<PRE CLASS="examplecode">    public String getName() {
        String trimmedNameKey = &quot;goto-cpp-switch-file&quot;; //NOI18N
        String fullNameKey = &quot;CTL_CppSwitchAction&quot;; //NOI18N
        if (isEnabled()) {
            switch (getToggleInfo(getActivatedNodes())) {
                case NodeKind.HEADER:
                    trimmedNameKey = &quot;goto-cpp-header-file&quot;; //NOI18N
                    fullNameKey = &quot;CppGoToHeaderFileAction&quot;; //NOI18N
                    break;
                case NodeKind.SOURCE:
                    trimmedNameKey = &quot;goto-cpp-source-file&quot;; //NOI18N
                    fullNameKey = &quot;CppGoToSourceFileAction&quot;; //NOI18N
                    break;
            }
        }
        String trimmedName = NbBundle.getMessage(CppSwitchAction.class, trimmedNameKey);;
        putValue(ExtKit.TRIMMED_TEXT, trimmedName);
        putValue(BaseAction.POPUP_MENU_TEXT, trimmedName);
        return NbBundle.getMessage(CppSwitchAction.class, fullNameKey);
    } 
    
    private static final class NodeKind {
        private static final int HEADER = 1;
        private static final int SOURCE = 2;
        private static final int NONE = 0;
    }
    
    private int getToggleInfo(Node[] activatedNodes) {
        if (activatedNodes != null &amp;&amp; activatedNodes.length == 1) {
            if (activatedNodes[0].getLookup().lookup(HDataObject.class) != null) {
                return NodeKind.SOURCE;
            } else if (activatedNodes[0].getLookup().lookup(CCDataObject.class) != null ||
                    activatedNodes[0].getLookup().lookup(CDataObject.class) != null) {
                return NodeKind.HEADER;
            }
        }
        return NodeKind.NONE;
} </PRE><P STYLE="margin-bottom: 0.2in">
    <BR><BR>
</P>
<H3 STYLE="margin-bottom: 0.2in">Use Action</H3>
<P STYLE="margin-bottom: 0.2in">Right-click the &ldquo;C/C++ Switch
    Files&rdquo; project node and choose <TT>Install/Reload in
    Development IDE</TT>. Open newfile.cc or newfile.h, make sure context
    menu has short name for action. Also check, that name is file-type
sensitive.</P>
<P STYLE="margin-bottom: 0.2in"><IMG SRC="goto-source.png" NAME="Switch to source" ALIGN=LEFT BORDER=0><BR CLEAR=LEFT><BR><BR>
</P>
<!--
<P STYLE="margin-bottom: 0.2in"><IMG SRC="switch-to-header.png" NAME="Switch to header" ALIGN=LEFT BORDER=0><BR CLEAR=LEFT><BR><BR>
</P>
-->
<H3 STYLE="margin-bottom: 0.2in">
Downloads</H3>
<P STYLE="margin-bottom: 0.2in">Download <A HREF="CppSwitchFiles.tar.gz">sources</A> of the tutorial or result <A HREF="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=3359">nbm</A> files.</P>
</BODY>
</HTML>

Project Features

About this Project

CND was started in November 2009, is owned by DimaZh, and has 197 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close