<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Hulles - NetBeans</title>
    <link>http://hulles.supersized.org/</link>
    <description>generating stack traces so you don't have to</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.3-alpha1 - http://www.s9y.org/</generator>
    <pubDate>Thu, 07 Aug 2008 19:22:40 GMT</pubDate>

    <image>
        <url>http://hulles.supersized.org/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Hulles - NetBeans - generating stack traces so you don't have to</title>
        <link>http://hulles.supersized.org/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>Son Of GeeWhiz Prolog: Olio</title>
    <link>http://hulles.supersized.org/archives/14-Son-Of-GeeWhiz-Prolog-Olio.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/14-Son-Of-GeeWhiz-Prolog-Olio.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=14</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=14</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;p&gt;&lt;em&gt;This article describes an enhancement to GeeWhiz Prolog, a project to implement the Prolog language in the NetBeans IDE. See the &lt;a href=&quot;http://hulles.supersized.org/pages/geewhiz.html&quot; alt=&quot;GeeWhiz Prolog Home Page&quot;&gt;GeeWhiz Prolog home page&lt;/a&gt; for more information.&lt;/em&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In this installment of &lt;strong&gt;Son of GeeWhiz Prolog&lt;/strong&gt; there really won&#039;t be much tutorial content. I&#039;ll do my best, but to be honest it&#039;s been long enough since I made the changes described here that I haven&#039;t been able to reassemble my notes properly, and I misplaced my screenshots. However I thought it would be better to post the new version of the source and NBM on the &lt;a href=&quot;http://hulles.supersized.org/pages/geewhiz.html&quot; alt=&quot;GeeWhiz Prolog Home Page&quot;&gt;GeeWhiz Prolog home page&lt;/a&gt; rather than wait any longer. So here you go. I am not including separate source code in this article, so you&#039;ll need to download the source on the Home Page to find the changes. Dang, sorry.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Moving the Satellite Window to the Navigator&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Probably the most obvious change is that the satellite view of the Prolog diagram has been transformed from a standalone JFrame window into a TopComponent that nestles into the Navigator window area. This is more convenient as it stays out of the way but remains accessible as you scroll around the larger diagram. It also makes us a &quot;better NetBeans citizen&quot;: standalone JFrames &lt;strong&gt;bad&lt;/strong&gt;, TopComponents &lt;strong&gt;good&lt;/strong&gt;. We&#039;re leaving the popup code JFrame windows alone however, so I guess we&#039;re not &lt;em&gt;that&lt;/em&gt; good a NetBeans citizen.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Another change is that we got rid of VPrologAction.java, which was the action living in the &quot;Window&quot; menu that opened up the demo/dummy diagram. Along with that, we eliminated the code in VPrologGraphScene to create the dummy diagram, and we added code to VPrologTopComponent to open and close the satellite navigator component. The final change regarding the satellite window is that we changed the &quot;show / hide satellite&quot; action in the right-click context menu in the main diagram. It is now just &quot;show satellite&quot;, since you can close the satellite window like any other window whenever you want.&lt;/p&gt;

&lt;br /&gt;&lt;h3&gt;Minor Stuff&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In the process of cleaning up GeeWhiz, it seemed to make more sense for the popup editor code to live in SceneUtils, so there it now resides. I also changed the phrase &quot;1 instances&quot; to read &quot;1 instance&quot; in the case where there is only 1 instance. Hey, it is &lt;em&gt;too&lt;/em&gt; rocket science.&lt;/p&gt;

&lt;br /&gt;&lt;h3&gt;Problems, Setbacks and Failures&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;For Son 2 (this article) I wanted to experiment with FreeMarker, which is a scripting language that one can use to insert text into a template. This can automatically insert licensing information or whatever else you want into our trusty Prolog program template. Unfortunately I could not get it to work reliably. In the newest version of the source code I left the FreeMarker code in, but every time I tried to execute it outside of the top level of the source code I got a cryptic error:&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
WARNING [org.openide.WizardDescriptor]
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
	at java.lang.String.substring(String.java:1938)
	at java.lang.String.substring(String.java:1905)
	...
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;Ouch. As I mentioned this only happened when the template was not in the top level of the source, for some reason. I puzzled over it for a while then gave it up as a bad job. But I thought I&#039;d pass it along anyway. I guess GeeWhiz Prolog was not destined to be the kind of application that has source code licenses....&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Another experiment I thought I would try was to use the capability of the Visual Library to directly associate objects with scene nodes. This would allow us to eliminate the Prolog object lookup we need to do to translate from node to Prolog clause. Hmmm, I thought, simpler is better, it sounds good. However, I hammered away at associating any kind of object with the nodes in our diagram scene and kept getting assertion errors in the Visual Library that didn&#039;t tell me what the hell was wrong. I finally traced the VL source code and found out that in a GraphScene there is already an object associated with a node that lurks behind the scenes. At least I think that&#039;s what&#039;s happening; it looks like a String is hooked up to a node as an object, and you can only have one object per node. Consequently, we can&#039;t hook up our Prolog clauses to nodes that way unless we quit using GraphScene, which is a poor trade. So the list association we started with remains intact, bloody but unbowed. As a footnote, I&#039;ve used the Visual Library a great deal since the experiment I described above, and every time I get an accursed assertion error from VL I know that it&#039;s a problem with trying to add multiple objects to a node. That would probably be a good thing to fix in the next release of the Visual Library. And it&#039;s a good thing to know if you&#039;re working with it.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Almost forgot - another problem I encountered has nothing directly to do with NetBeans: I have been trying to get some HTML windows to pop up from this blog platform that don&#039;t have the sidebars etc. so I can better display a few &lt;strong&gt;&lt;large&gt;movies&lt;/large&gt;&lt;/strong&gt; I made using Wink that demonstrate the use of GeeWhiz Prolog. I haven&#039;t been able accomplish that so I am posting the Flash videos just as links on the GeeWhiz Prolog home page. Check them out. I created the movies so that people who are interested in Prolog but who don&#039;t care to know anything about NetBeans can see what the program does without going through the process of downloading NetBeans and learning the IDE. I&#039;m nice like that.&lt;/p&gt;

&lt;br /&gt;&lt;h3&gt;Going Further&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Well, sort of a lame &lt;strong&gt;Son of GeeWhiz Prolog&lt;/strong&gt;, I know, but I didn&#039;t want to post the updated source code and not provide an explanation to go with it. I don&#039;t have plans to post anything new here for a while as I am in the middle of a large project utilizing NetBeans, unless.... Well, we&#039;ll see.&lt;/p&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;Files From This Entry&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;(see the newly posted source code zip files and NBM on the &lt;a href=&quot;http://hulles.supersized.org/pages/geewhiz.html&quot; alt=&quot;GeeWhiz Prolog Home Page&quot;&gt;GeeWhiz Prolog home page&lt;/a&gt;.)&lt;/p&gt;
&lt;br /&gt; 
    </content:encoded>

    <pubDate>Thu, 07 Aug 2008 21:10:57 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/14-guid.html</guid>
    
</item>
<item>
    <title>Son Of GeeWhiz Prolog: Improving The Diagram</title>
    <link>http://hulles.supersized.org/archives/12-Son-Of-GeeWhiz-Prolog-Improving-The-Diagram.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/12-Son-Of-GeeWhiz-Prolog-Improving-The-Diagram.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=12</wfw:comment>

    <slash:comments>5</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=12</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;p&gt;&lt;em&gt;This article describes an enhancement to GeeWhiz Prolog, a project to implement the Prolog language in the NetBeans IDE. See the &lt;a href=&quot;http://hulles.supersized.org/pages/geewhiz.html&quot; alt=&quot;GeeWhiz Prolog Home Page&quot;&gt;GeeWhiz Prolog home page&lt;/a&gt; for more information.&lt;/em&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;In this add-on to our GeeWhiz Prolog project, we&#039;re going to add some new features and Geewhizability to our predicate modeler. Big thanks go to David Kaspar who provided the Visual Library examples from which much of this material is &lt;strike&gt;stolen&lt;/strike&gt; taken. The examples are located in the &quot;main/contrib&quot; section of the NetBeans Mercurial repository (although I haven&#039;t updated my own library yet to reflect this). You can find them at this link: &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/hg.netbeans.org/main/contrib/file/&#039;);&quot; href=&quot;http://hg.netbeans.org/main/contrib/file/&quot; title=&quot;Visual Library examples&quot;&gt;http://hg.netbeans.org/main/contrib/file/&lt;/a&gt; under &quot;visual.examples&quot;.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Adding An Export Function&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;The first change we&#039;re going to make to our nifty Prolog predicate diagrammer is that we&#039;re going to add a means by which we can export our diagram to a Portable Network Graphics (PNG) file. Once we have a PNG file, we can print it, email it to Aunt Margaret in Philly, or (hypothetically) stick it on our GeeWhiz Prolog home page. So let&#039;s get started.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;First, create a new Java class in your project called &quot;SceneExport&quot;. Replace the empty class with this:&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
public class SceneExport {

    public void exportScene(VMDGraphScene scene) {
        JComponent view;
        Dimension dim;
        BufferedImage bufImage;
        Graphics2D graphics;
        File file;
        
        view = scene.getView();
        dim = view.getSize();
        bufImage = new BufferedImage (dim.width, dim.height,
                BufferedImage.TYPE_4BYTE_ABGR);
        graphics = bufImage.createGraphics ();
        scene.paint (graphics);
        graphics.dispose ();
        file = getPNGSaveFile(view);
        if (file != null) {
            diagramToPNG(file, bufImage);
        }
    }
    
    private File getPNGSaveFile (JComponent view) {
        JFileChooser chooser;
        File file;
        
        //TODO: save selected directory as default for next time
        chooser = new JFileChooser();
        chooser.setDialogTitle(&quot;Export Scene As ...&quot;);
        chooser.setDialogType(JFileChooser.SAVE_DIALOG);
        chooser.setMultiSelectionEnabled(false);
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        chooser.setFileFilter(new FileFilter() {
            public boolean accept(File file) {
                if (file.isDirectory())
                    return true;
                return file.getName().toLowerCase().endsWith(&quot;.png&quot;);
            }
            public String getDescription () {
                return &quot;Portable Network Graphics (.png)&quot;;
            }
        });
        if (chooser.showSaveDialog (view) != JFileChooser.APPROVE_OPTION) {
            return null;
        }
        
        file = chooser.getSelectedFile ();
        if (! file.getName ().toLowerCase ().endsWith (&quot;.png&quot;))
            file = new File (file.getParentFile (), file.getName () + &quot;.png&quot;);
        if (file.exists ()) {
            DialogDescriptor descriptor = new DialogDescriptor (
                    &quot;File (&quot; + file.getAbsolutePath () + 
                    &quot;) already exists. Do you want to overwrite it?&quot;,
                    &quot;File Exists&quot;, true, DialogDescriptor.YES_NO_OPTION,
                    DialogDescriptor.NO_OPTION, null);
            DialogDisplayer.getDefault().createDialog(descriptor).setVisible(true);
            if (descriptor.getValue() != DialogDescriptor.YES_OPTION) {
                return null;
            }
        }
        return file;
    }
    
    private void diagramToPNG(File file, BufferedImage bufImage) {
        
        try {
            ImageIO.write (bufImage, &quot;png&quot;, file); // NOI18N
        } catch (IOException e) {
            ErrorManager.getDefault ().notify (e);
        }
    }
}
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;What the above code does is copy the predicate diagram graphics to a BufferedImage then save the image to a PNG file. Pretty straightforward, and taken from Visual Library example code that I haven&#039;t been able to find again. So fix imports, save and close the SceneExport class then create a new Java class called &quot;SceneUtils&quot;. Replace the empty class with this code:&lt;/p&gt;
&lt;strong&gt;&lt;pre&gt;
public class SceneUtils {
    private static final String EXPORT_SCENE = &quot;export&quot;;
    private static final String ACTION_MOVE = &quot;move&quot;;
    private static final String REMOVE_LABEL = &quot;remove&quot;;
    private static final String REPLACE_LABEL = &quot;replace&quot;;
    private LabelWidget label;
    private Scene scene = null;
    private boolean isVMD;
    
    public SceneUtils(Scene scene) {
        this.scene = scene;
        isVMD = scene instanceof VMDGraphScene;
    }

    public void addContextMenu() {
        WidgetAction popup;
        
        if (scene == null) {
            return;
        }
        label = new LabelWidget (scene, &quot;Right-click to open popup menu.&quot;);
        label.setPreferredLocation (new Point (100, 100));
        scene.addChild (label);
        
        popup = ActionFactory.createPopupMenuAction (new MyPopupProvider ());

        scene.getActions ().addAction (popup);

        // leave popup menu up (?)
        scene.createActions (ACTION_MOVE).addAction (popup); 
        label.createActions (ACTION_MOVE).addAction (ActionFactory.
                createMoveAction ());
    }

    private void exportScene() {
        SceneExport exporter;

        if (isVMD) {
            // TODO: thread
            exporter = new SceneExport();
            exporter.exportScene((VMDGraphScene) scene);
        }
    }
    
    private void addMoveAction() {
        
        scene.setActiveTool(ACTION_MOVE);
    }
    
    private void removeLabel() {
        
        // removes it from the scene, doesn&#039;t delete it
        this.label.removeFromParent();
    }
    
    private void replaceLabel() {
        if (label.getParentWidget() == null) {
            scene.addChild(label);
            scene.validate();
        }
    }
    
    private final class MyPopupProvider implements PopupMenuProvider, 
            ActionListener {
        private JPopupMenu menu;

        public MyPopupProvider () {
            menu = new JPopupMenu (&quot;Popup menu&quot;);
            JMenuItem item;

            if (isVMD) {
                item = new JMenuItem (&quot;Export scene to PNG...&quot;);
                item.setActionCommand (EXPORT_SCENE);
                item.addActionListener (this);
                menu.add (item);
            }

            item = new JMenuItem (&quot;Move the label&quot;);
            item.setActionCommand (ACTION_MOVE);
            item.addActionListener (this);
            menu.add (item);

            item = new JMenuItem (&quot;Delete the label&quot;);
            item.setActionCommand (REMOVE_LABEL);
            item.addActionListener (this);
            menu.add (item);

            item = new JMenuItem (&quot;Replace the label&quot;);
            item.setActionCommand (REPLACE_LABEL);
            item.addActionListener (this);
            menu.add (item);

        }

        public JPopupMenu getPopupMenu (Widget widget, Point localLocation) {
            return menu;
        }

        public void actionPerformed (ActionEvent e) {
            String cmd;
            
            cmd = e.getActionCommand ();
            if (cmd.equals(EXPORT_SCENE)) {
                exportScene();
            } else if (cmd.equals(ACTION_MOVE)) {
                addMoveAction();
            } else if (cmd.equals(REMOVE_LABEL)) {
                removeLabel();
            } else if (cmd.equals(REPLACE_LABEL)) {
                replaceLabel();
            }
        }
    }
}
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;In SceneUtils we&#039;re creating a context menu that pops up when you right-click on our lovely model diagram. In this incarnation it was written to cope with any kind of Scene even though the export function only handles VMDGraphScene. The menu includes some choices that are of limited utility in practice but serve to demonstrate the capability of the right-click popup. We also introduce the LabelWidget, which we haven&#039;t seen before. So fix imports, save and close the SceneUtils file.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Finally, we&#039;re going to change the VPrologGraphScene class to use our SceneUtils class. At the beginning of each constructor, add the following code:&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
        SceneUtils sceneUtils;

        sceneUtils = new SceneUtils(this);
        sceneUtils.addContextMenu();
&lt;/pre&gt;&lt;/strong&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-0a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:125 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-0a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;At the very end of each constructor, add this line:
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
        layoutScene();
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;I found the &quot;layoutScene&quot; method by accident when I was working through some of David Kaspar&#039;s Visual Library examples. It automatically cleans up our diagram! Evidentally there is a more robust orthogonal link router in the works, but for our purposes this one works just fine and eliminates much of the haphazardness of the random way we were placing nodes before. Woohoo!&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Save and close the file. Now we&#039;re ready to test the beast. Clean and build the project, then install it to the target IDE. (You missed doing that since completing the original GeeWhiz project, didn&#039;t you?) Open your Algorithms project and wait for the indexing to stop. Now we&#039;re ready to check out our new popup menu. Open the sieve.pro file (or any other Prolog file) and wait for the Navigator to fill in the statements and for the syntax to color. Then go to the menu and click &quot;View&quot; &quot;Show Prolog Diagram&quot; to bring up the predicate model of our program. (&quot;Gee whiz!&quot;) Right-click on the diagram to get our popup menu.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:126 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-1a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

First, try moving, deleting and re-adding the label. Then, when you&#039;re tired of playing with that, try exporting the diagram to a PNG file. Cool, eh? If you monkey around with it enough, however, you&#039;ll notice that if you zoom and pan the diagram prior to exporting the PNG the export doesn&#039;t work exactly right. For now my solution for this glitch is: &lt;em&gt;don&#039;t zoom or pan the diagram prior to exporting the PNG&lt;/em&gt;. Someday I&#039;ll look into fixing this; I think that maybe I need to get the dimensions from something other than the view graphics. But we have other things to do now, so let&#039;s leave it alone.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;And by the way, don&#039;t forget to gasp with delight at the way layoutScene() fixes up our diagram when it is first displayed! When you&#039;re done testing and fooling around you can close the target IDE.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Adding Editor Windows To Nodes&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;The next feature we&#039;re going to add is a window containing the text Prolog source code for the predicate that opens up when we double-click on a predicate node. You wondered why we built the text into our PrologClause class, didn&#039;t you? This is why. First, create a new  JFrame Java class called &quot;NodeContents&quot; by right-clicking on the package and selecting &quot;New&quot; &quot;JFrame Form...&quot; This is going to be the window in which we display our source code. In the &quot;Design&quot; view, add a scroll pane that snaps to the preferred borders of the frame and then add a text area that fills the scroll pane. Rename the text area to &quot;textArea&quot;, then in Properties give it a descriptive tool tip, unclick the &quot;editable&quot; property and change the tab size to 4. In the JFrame properties, change the defaultCloseOperation to &quot;HIDE&quot;. Switch to &quot;Source&quot; and delete the Main method. Right below the constructor, insert the following code:&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
    public void setText(String text) {
        textArea.setText(text);
    }
    
    public void changeTitle(String title) {
        this.setTitle(title);
    }
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;Save and close the file. Now open VPrologGraphScene and replace the whole VPrologGraphScene class with this:&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
 public class VPrologGraphScene extends VMDGraphScene {
    private static final Image IMAGE_NODE = Utilities.
            loadImage (&quot;org/hulles/geewhiz/node.png&quot;); // NOI18N
    private static final Image IMAGE_EXTERNAL = Utilities.
            loadImage (&quot;org/hulles/geewhiz/external.png&quot;); // NOI18N
    private static final Image IMAGE_ITEM = Utilities.
            loadImage (&quot;org/hulles/geewhiz/item.gif&quot;); // NOI18N
    private static int pinID = 1;
    private static int edgeID = 1;
    private List&amp;lt;PrologClause&amp;gt; clauses;

    /** Creates a new instance of VPrologGraphScene */
    public VPrologGraphScene() { // demo
        SceneUtils sceneUtils;

        sceneUtils = new SceneUtils(this);
        sceneUtils.addContextMenu();
        
        createNode (this, 100, 100, IMAGE_NODE, &quot;Clause1&quot;, &quot;Internal&quot;, null);
        createPin (this, &quot;Clause1&quot;, &quot;start&quot;, IMAGE_ITEM, &quot;Start&quot;, &quot;Element&quot;);
        createNode (this, 400, 100, IMAGE_NODE, &quot;Clause2&quot;, &quot;External&quot;,
                Arrays.asList (IMAGE_EXTERNAL));
        createPin (this, &quot;Clause2&quot;, &quot;ok&quot;, IMAGE_ITEM, &quot;okCommand1&quot;, &quot;Command&quot;);
        createEdge (this, &quot;start&quot;, &quot;Clause2&quot;);
        createEdge (this, &quot;ok&quot;, &quot;Clause1&quot;);
        layoutScene();
    }
    public VPrologGraphScene(DataObject dObj) {
        PrologAST pTree;
        List&amp;lt;PrologClause&amp;gt; embedded;
        String nodeID;
        Integer instances;
        String newPinID;
        PrologClause existingClause;
        String eNodeID;
        List&amp;lt;String&amp;gt; eNodes;
        SceneUtils sceneUtils;
        VMDNodeWidget node;

        sceneUtils = new SceneUtils(this);
        sceneUtils.addContextMenu();
        
        pTree = new PrologAST(dObj);
        clauses = pTree.getClauses();
        // create all primary nodes first so they&#039;re available
        //   to create edges to....
        for (PrologClause clause : clauses) {
            instances = clause.getInstanceCount();
            nodeID = makeNodeID(clause);
            node = createNode(this, randXPoint(), randYPoint(), 
                    IMAGE_NODE, nodeID, instances.toString() + &quot; instances&quot;, null);
            addEditor(node, clause);
        }
        // now create pins and edges
        eNodes = new ArrayList&amp;lt;String&amp;gt;();
        for (PrologClause clause : clauses) {
            nodeID = makeNodeID(clause);
            embedded = clause.getBody();
            for (PrologClause e : embedded) {
                eNodeID = makeNodeID(e);
                newPinID = &quot;pin&quot; + VPrologGraphScene.pinID++;
                createPin(this, nodeID, newPinID, 
                        IMAGE_ITEM, eNodeID, &quot;Embedded&quot;);
                existingClause = PrologClause.findClause(clauses, e);
                if (existingClause == null) {
                    if (!eNodes.contains(eNodeID)) {
                    // externally defined (?)
                        createNode(this, randXPoint(), randYPoint(), 
                                IMAGE_NODE, eNodeID, &quot;External&quot;,
                                Arrays.asList (IMAGE_EXTERNAL));
                        eNodes.add(eNodeID);
                    }
                }
                createEdge(this, newPinID, eNodeID);
            }
        }
        layoutScene();
    }

    private String makeNodeID(PrologClause clause) {
        String name;
        Integer arity;
        
        name = clause.getName();
        arity = clause.getArity();
        return name + &quot;/&quot; + arity.toString();
    }
    
    private int randXPoint() {
        return (int) (Math.random() * 800);
    }
    
    private int randYPoint() {
        return (int) (Math.random() * 800);
    }
    
    private VMDNodeWidget createNode (VMDGraphScene scene, int x, int y, 
            Image image, String name, String type, List&amp;lt;Image&amp;gt; glyphs) {
        VMDNodeWidget widget;
        
        widget = (VMDNodeWidget) scene.addNode (name);
        widget.setPreferredLocation (new Point (x, y));
        widget.setNodeProperties (image, name, type, glyphs);
        scene.addPin (name, name + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX);
        return widget;
    }

    private void createPin (VMDGraphScene scene, String nodeID, String pinID, 
            Image image, String name, String type) {
        VMDPinWidget pinWidget;
        
        pinWidget = (VMDPinWidget) scene.addPin (nodeID, pinID);
        pinWidget.setProperties (name, null);
    }

    private void createEdge (VMDGraphScene scene, String sourcePinID, 
            String targetNodeID) {
        String localEdgeId;
        
        localEdgeId = &quot;edge&quot; + VPrologGraphScene.edgeID ++;
        scene.addEdge (localEdgeId);
        scene.setEdgeSource (localEdgeId, sourcePinID);
        scene.setEdgeTarget (localEdgeId, targetNodeID + 
                VMDGraphScene.PIN_ID_DEFAULT_SUFFIX);
    }

    private void addEditor(VMDNodeWidget node, PrologClause clause) {
        NodeEditor editor;
        WidgetAction nodeAction;

        editor = new NodeEditor(clause);
        nodeAction = ActionFactory.createEditAction(editor);
        node.getActions().addAction(nodeAction);
    }
    
    public void newLayout() {
        layoutScene();
    }
    
    private class NodeEditor implements EditProvider {
        private final PrologClause clause;
        private final String popupTitle;
        private final String popupText;
        private NodeContents popup;
        
        public NodeEditor(PrologClause clause) {
            this.clause = clause;
            this.popup = null;
            popupTitle = makeNodeID(clause);
            popupText = clause.getText();
        }

        public void edit(Widget node) {
            // assumes read-only text
            VMDNodeWidget myNode;
            
            myNode = (VMDNodeWidget) node;
            
            // lazy edit window construction
            if (popup == null) {
                java.awt.EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        popup = new NodeContents();
                        popup.changeTitle(popupTitle);
                        popup.setText(popupText);
                        popup.setVisible(true);
                    }
                });
            } else {
                popup.setVisible(true);
            }
        }
        
    }
}
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;What we&#039;re doing here is, for every defined node (as opposed to external node) that we create, we&#039;re adding an EditAction that creates a NodeContents window when the node is double-clicked. We hold off actually creating the NodeContents window until the node is double-clicked so we can be a good NetBeans neighbor. Also, notice that instead of disposing of the window when we close it we just hide it so we can set it visible again the next time it&#039;s clicked.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Adding A Satellite Window&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Before we test the editor functionality we&#039;re going to go ahead and make another window that shows the entire diagram in miniature, called in Visual Library terms a satellite view. We&#039;re going to show it and hide it &lt;em&gt;via&lt;/em&gt; our context menu. So create another new JFrame called NodeSatelliteView.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;In &quot;Design&quot; mode add a panel to the frame that takes up the whole frame and make it &quot;BorderLayout&quot;. Change the name from jPanel1 to satellitePanel and give it a tooltip &quot;Prolog diagram satellite view&quot;. Change the JFrame defaultCloseOperation to &quot;HIDE&quot; and the title to &quot;Prolog Satellite View&quot;.
Switch to &quot;Source&quot; mode, remove the Main method, and add this method below the constructor.&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
    public void addView(JComponent view) {
        
        satellitePanel.removeAll();
        satellitePanel.add(view);
    }
&lt;/pre&gt;&lt;/strong&gt;
&lt;br  /&gt;
&lt;p&gt;Save and close the file. Now open &quot;SceneUtils&quot; and replace the entire class with this.&lt;/p&gt;
&lt;br /&gt;
&lt;strong&gt;&lt;pre&gt;
public class SceneUtils {
    private static final String EXPORT_SCENE = &quot;export&quot;; // NOI18N
    private static final String LAYOUT_SCENE = &quot;layout&quot;; // NOI18N
    private static final String PRINT_SCENE = &quot;print&quot;; // NOI18N
    private static final String SATELLITE_VIEW = &quot;satellite&quot;; // NOI18N
    private VPrologGraphScene scene = null;
    private NodeSatelliteView viewer;
    
    public SceneUtils(VPrologGraphScene scene) {
        this.scene = scene;
    }

    public void addContextMenu() {
        WidgetAction popup;
        
        if (scene == null) {
            return;
        }
        
        popup = ActionFactory.createPopupMenuAction (new MyPopupProvider ());
        scene.getActions ().addAction (popup);
        // leave popup menu up (?)
        scene.createActions (LAYOUT_SCENE).addAction (popup);
    }

    private void exportScene() {
        SceneExport exporter;

        // TODO: thread
        exporter = new SceneExport();
        exporter.exportScene((VMDGraphScene) scene);
    }
    
    private void reLayoutScene() {
        
         scene.newLayout();
    }
    
    private void printScene() {
        // not yet implemented
    }
    
    private void makeSatelliteView() {
        
        if (viewer == null) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    JComponent view;

                    viewer = new NodeSatelliteView();
                    view = scene.createSatelliteView();
                    viewer.addView(view);
                    viewer.setVisible(true);
                }
            });
        } else {
            if (viewer.isVisible()) {
                viewer.setVisible(false);
            } else {
                viewer.setVisible(true);
            }
        }
        
    }
    
    private final class MyPopupProvider implements PopupMenuProvider, ActionListener {
        private JPopupMenu menu;

        public MyPopupProvider () {
            menu = new JPopupMenu (&quot;Popup menu&quot;);
            JMenuItem item;

            item = new JMenuItem (&quot;Print scene...&quot;);
            item.setActionCommand (PRINT_SCENE);
            item.addActionListener (this);
            menu.add (item);

            item = new JMenuItem (&quot;Export scene to PNG...&quot;);
            item.setActionCommand (EXPORT_SCENE);
            item.addActionListener (this);
            menu.add (item);

            item = new JMenuItem (&quot;Redo scene layout&quot;);
            item.setActionCommand (LAYOUT_SCENE);
            item.addActionListener (this);
            menu.add (item);

            item = new JMenuItem (&quot;Show / hide satellite view&quot;);
            item.setActionCommand (SATELLITE_VIEW);
            item.addActionListener (this);
            menu.add (item);

        }

        public JPopupMenu getPopupMenu (Widget widget, Point localLocation) {
            return menu;
        }

        public void actionPerformed (ActionEvent e) {
            String cmd;
            
            cmd = e.getActionCommand ();
            if (cmd.equals(EXPORT_SCENE)) {
                exportScene();
            } else if (cmd.equals(PRINT_SCENE)) {
                printScene();
            } else if (cmd.equals(LAYOUT_SCENE)) {
                reLayoutScene();
            } else if (cmd.equals(SATELLITE_VIEW)) {
                makeSatelliteView();
            }
        }

    }
}
&lt;/pre&gt;&lt;/strong&gt;
&lt;br /&gt;
&lt;p&gt;Notice that we got rid of the label and label actions and tailored the class to be specific to our Prolog needs instead of generic. We added an empty printing function, a layout function, and a satellite view function to our context menu and implemented the satellite view within the class. Fix imports, save and close the file. Now we&#039;re ready to test the work we&#039;ve done. You&#039;ll like this.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Testing The New Diagram&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Clean and build the main project, then install to the target IDE. Open the &quot;Algorithms&quot; project and open &quot;sieve.pro&quot;. When the Navigator comes up, start up the modeler (&quot;View&quot; &quot;Show Prolog Diagram&quot;) and double-click on a node. If the node is defined and not external then a window should open with the text of all the clauses that make up the predicate.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-2a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:127 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-2a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Notice that you can open more than one predicate window at a time but only one window per node, which makes sense within the context of the diagram.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-2b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:128 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-2b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Now right-click on the diagram to bring up our context menu.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-3a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:129 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-3a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Move a node or two then try out the &quot;Redo layout&quot; function. Hold your breath, then try &quot;Show / hide satellite view&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/son1-3b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:130 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/son1-3b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Move the cursor around on the satellite view and watch what happens to your underlying diagram.  Gee whiz! Pretty awesome, right? To close the satellite view you can click &quot;Show / hide...&quot; again in the context menu or just close the window. As you might suspect, the satellite view is not very useful with small diagrams like the one sieve.pro generates, but with a larger diagram like that in the screen shot it can be very useful indeed. Plus, it&#039;s just plain fun to have it around.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Going Further&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;One of the funky things about what we accomplished in this entry is that the screens for the node text and the screen for the satellite window are all JFrames independent of the diagram TopComponent. If you close the diagram, the frames stick around anyway. While you could possibly make a case that the little text windows are useful independently of the diagram, at least the satellite window should be dependent on the TopComponent and go away when it goes away. It is not useful without the diagram. So a reasonable next step would be to make the &quot;pop up&quot; screens for node text and the satellite window JDialogs or close them when the TopComponent goes away.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Now that we have all these new features on our diagram, what else could we do? The first thing that comes to mind is to allow the user to edit the code in the popup node window and have the changes reflected in the editor window source code. This would take some careful design because of the way multiple clauses make up a predicate, but it could certainly be done using techniques we&#039;ve already looked at. We could disembowel the PrologAST class and store line and column numbers in PrologClause, then use the same way we pop into the source code from the output window to go into the editor and change the text. But the usefulness of editing directly in the popup window is pretty questionable, at least for Prolog programming, so we won&#039;t go that route. I won&#039;t, anyway, but &lt;em&gt;you&lt;/em&gt; certainly can...&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;An even more interesting (to me) idea is to use the stuff we learned in GeeWhiz to write a &lt;strong&gt;whole new language interface&lt;/strong&gt;. It would be based on Java but instead of writing code you would just manipulate nodes and edges then compile the diagram! Theoretically a person would not even have to know Java to &quot;program&quot; with this new language. I know, I know, it sounds like UML but it would be way cooler. Actually, this is something I&#039;ve always wanted to develop, so look for &quot;Project PipeDreams&quot; coming your way soon....&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Files From This Entry&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_son1.tar.gz&#039;&gt;geewhiz_son1.tar.gz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a onclick=&quot;javascript:urchinTracker(&#039;/download/uploads/geewhiz/geewhiz_son1.zip&#039;);&quot; href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_son1.zip&#039;&gt;geewhiz_son1.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Tue, 27 May 2008 00:33:51 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/12-guid.html</guid>
    
</item>
<item>
    <title>GeeWhiz Prolog - Part Eight - Creating An NBM</title>
    <link>http://hulles.supersized.org/archives/11-GeeWhiz-Prolog-Part-Eight-Creating-An-NBM.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/11-GeeWhiz-Prolog-Part-Eight-Creating-An-NBM.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=11</wfw:comment>

    <slash:comments>8</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=11</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;em&gt;&lt;p&gt;This is Part Eight, the ninth and final part of a series of entries describing an implementation of the Prolog language in the NetBeans IDE. &lt;/p&gt;
&lt;br/&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/2-GeeWhiz-Prolog-Part-Zero-About-the-Project.html&quot; alt=&quot;About the Project&quot;&gt;Part Zero, &quot;About The Project,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/3-GeeWhiz-Prolog-Part-One-Before-We-Start.html&quot; alt=&quot;Before We Start&quot;&gt;Part One, &quot;Before We Start,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/4-GeeWhiz-Prolog-Part-Two-Creating-A-File-Type.html&quot; alt=&quot;Creating A File Type&quot;&gt;Part Two, &quot;Creating A File Type,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/5-GeeWhiz-Prolog-Part-Three-Adding-Language-Support.html&quot; alt=&quot;Adding Language Support&quot;&gt;Part Three, &quot;Adding Language Support,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html&quot; alt=&quot;A Visual Prolog Modeler&quot;&gt;Part Four, &quot;A Visual Prolog Modeler&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html&quot; alt=&quot;Adding The Compiler&quot;&gt;Part Five, &quot;Adding The Compiler&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/8-GeeWhiz-Prolog-Part-Six-Creating-Prolog-Projects.html&quot; alt=&quot;Creating Prolog Projects&quot;&gt;Part Six, &quot;Creating Prolog Projects&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/9-GeeWhiz-Prolog-Part-Seven-Adding-An-Option-Panel.html&quot; alt=&quot;Adding An Option Panel&quot;&gt;Part Seven, &quot;Adding An Option Panel&quot; is here.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Well, we&#039;ve come a long way. Our NetBeans-embedded Prolog IDE has grown like Topsy (whoever Topsy is) and now threatens to take over NetBeans entirely and make everyone program in Prolog instead of Java. Okay, maybe not, but it &lt;em&gt;has&lt;/em&gt; come a long way as I said. We will look at what we&#039;ve accomplished in a &lt;em&gt;post mortem&lt;/em&gt; in a little bit, but right now let&#039;s create a NetBeans plug-in module (NBM) from GeeWhiz Prolog and install the module into our development IDE at last.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Creating The NBM&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;As I&#039;m sure you&#039;ve noticed, one of the options on the GeeWhiz project context menu in NetBeans has always been &quot;Create NBM&quot;. Go ahead and clean and build GeeWhiz, right-click on the project and select &quot;Create NBM&quot; now.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-0a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:108 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-0a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

After some whirring and clanking &lt;em&gt;(note to self: backup Aspen files!)&lt;/em&gt; the IDE settles down again and you&#039;ve created the NBM file. Unless you have the output window open you might not even notice that anything happened as there is no user interaction for this process.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;What we&#039;ve done is generate a nifty little zip file called (in my case) &quot;org-hulles-geewhiz.nbm&quot; in the build folder of our project.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-0b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:109 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-0b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;strong&gt;At this point, you should save the NBM file to another directory.&lt;/strong&gt; I realized to my chagrin while writing this that the &quot;clean&quot; process in cleaning and building your project wipes out the build directory, including the NBM file. It&#039;s easy enough to regenerate, as we just saw, but still.... One wants to be sure the NBM file one thinks one has matches the file one thought one had, doesn&#039;t one? Yes one does, by golly.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;I&#039;m not sure you noticed in the above screenshot, but I had the properties for the NBM file open so you could see what I saw the first time I went through this process. &quot;Hmm,&quot; says I to myself. &quot;The size is a little larger than I thought it would be. And I guess the NetBeans folks forgot to put the &#039;kB&#039; on the size property. It&#039;s still too large to host as a download, though.&quot; Then I went and looked at the file in the folder just to make sure and it&#039;s &lt;em&gt;47kB&lt;/em&gt;! Dang, that&#039;s like buying a case of beer for a dollar, it just doesn&#039;t happen that often these days. So it&#039;s a little file, is my point, and I can stick it on my blog site as a download without a further thought. Hell, I can even email it as an attachment to my Aunt Margaret in Philly who still has dial-up. (Not sure she has NetBeans, though....)&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;So now what do we do with our brand new (and shrimpy little) NBM file? For one thing, if we wanted to we could make it available to the whole world &lt;em&gt;via&lt;/em&gt; the NetBeans Plug-In Download Center (or whatever it&#039;s called) but that&#039;s a bit outside the scope of this project and besides, it&#039;s not ready for implementation yet. But we &lt;em&gt;can&lt;/em&gt; use it to finally install GeeWhiz Prolog in our development IDE if we want to. So let&#039;s do that.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Installing The NBM In Your IDE&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;There is probably a more dignified way to install a local NBM into your IDE, but the way I found works pretty well so we&#039;ll use that. In the main menu of your development IDE click &quot;Tools&quot;, then &quot;Plugins&quot;. Once the Plugins manager has started, select the Downloads tab. Click the &quot;Add Plugins...&quot; button and navigate to your NBM file and select it.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:110 --&gt;&lt;img width=&quot;90&quot; height=&quot;59&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-1a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Now your new module looks all shiny and ready to go, doesn&#039;t it? You can change the information that shows up on the right by right-clicking the GeeWhiz project and selecting &quot;Properties&quot; and filling out the &quot;Display&quot; and &quot;Packaging&quot; tabs in the Properties window. Then of course you have to recreate your NBM file. Once you&#039;re ready to bite the bullet, select &quot;GeeWhiz Prolog&quot; then click the &quot;Install&quot; button.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-1b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:111 --&gt;&lt;img width=&quot;90&quot; height=&quot;78&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-1b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

On the first screen there isn&#039;t much to do but sit and admire the professional look of your work. When you&#039;re ready, click the &quot;Next&quot; button.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-1c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:112 --&gt;&lt;img width=&quot;90&quot; height=&quot;78&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-1c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

On the next screen, unless you created a GeeWhiz license when I wasn&#039;t looking, you can just go ahead and click &quot;Install&quot;. Ignore the &quot;not digitally signed&quot; messages you will generate unless you also signed it when you created the license, you rascal.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Eventually the IDE will come back and tell  you the module is installed. To check it, select &quot;Tools&quot; &quot;Module Manager&quot; from the main menu and there GeeWhiz Prolog is, under &quot;Language Support&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/nbm-2a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:113 --&gt;&lt;img width=&quot;90&quot; height=&quot;67&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/nbm-2a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Gee whiz! Ain&#039;t it great? Check it out in your IDE; all the functions we tested in the target IDE should be there. You might consider copying or moving the Algorithms project from the target project directory to your real project directory, just to have test fodder available.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Guess What - We&#039;re Done!&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;That wraps up our adventures with GeeWhiz Prolog, at least for now. I am in the process of creating a &lt;a href=&quot;http://hulles.supersized.org/pages/geewhiz.html&quot; title=&quot;GeeWhiz Prolog Home Page&quot;&gt;home page for GeeWhiz Prolog&lt;/a&gt; on my blog that you can check occasionally if you want. I will post the NBM there, plus a complete set of source files, plus a PDF of all the GeeWhiz blog entries for your convenience in downloading and reading offline. Any addenda and errata (as if) will be posted there as well. I already thought of one thing I forgot to mention, and that&#039;s that you can zoom in and out (ctrl + mouse button) and pan (hold middle mouse button) on the modeling diagrams we created earlier.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;As a special bonus for acting now, you will also receive an additional Java class in the complete source file archive called SceneExport.java that may or may not create a .PNG file from the modeling diagram. I&#039;m still working on it and haven&#039;t incorporated it into the diagram yet, but I&#039;m sure I&#039;ll write about it when I do. It&#039;s based on a slightly cryptic code segment in the Visual Library API and... Oh, just wait and read the article when I write it.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;It&#039;s hard to end this series. I feel like we just scratched the surface with GeeWhiz Prolog, but hey, the surface itched. So... ciao, it&#039;s been fun. I hope you found this series useful, informative and occasionally entertaining. -- Hulles&lt;/p&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;GeeWhiz Prolog Feature Summary&lt;/h3&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Incorporated as an integral part of the NetBeans IDE&lt;/li&gt;
&lt;li&gt;Has a WYSIWYG source code editor&lt;/li&gt;
&lt;li&gt;Provides Prolog syntax checking and highlighting&lt;/li&gt;
&lt;li&gt;Works with the sidebar statement navigator&lt;/li&gt;
&lt;li&gt;Generates a visual and interactive Prolog predicate model that personally rocks my world&lt;/li&gt;
&lt;li&gt;Supports in-line Prolog source code compilation with error lines linked back to source&lt;/li&gt;
&lt;li&gt;Is O/S- and compiler-independent&lt;/li&gt;
&lt;li&gt;Is installable as a plug-in module to the NetBeans IDE&lt;/li&gt;
&lt;li&gt;Is free&lt;/li&gt;
&lt;li&gt;The source code is easily modifiable since you build the damn thing yourself&lt;/li&gt;
&lt;li&gt;Did I mention it&#039;s free?&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;&lt;h3&gt;Going Further - My GeeWhiz Notes&lt;/h3&gt;&lt;br /&gt;
&lt;h4&gt;Fixes And Improvements To Current Features&lt;/h4&gt;
&lt;dl&gt;
&lt;dt&gt;Use public API for Generic Languages Framework&lt;/dt&gt;
&lt;dd&gt;Change PrologAST to not user ParserManagerImpl to get the AST root node so we can go back to the public API and not use an implementation version of GLF.&lt;/dd&gt;
&lt;dt&gt;Change Names To Be More Descriptive&lt;/dt&gt;
&lt;dd&gt;Change the name of the PrologClause class to PrologPredicate, e.g. In other words, refactor refactor refactor.&lt;/dd&gt;
&lt;dt&gt;Improve the Prolog grammar definition&lt;/dt&gt;
&lt;dd&gt;Improve the grammar defined in language.nbs for Prolog. I think it can be simplified and improved.&lt;/dd&gt;
&lt;dt&gt;Improve threading in GeeWhiz&lt;/dt&gt;
&lt;dd&gt;Analyze GeeWhiz and introduce threading, concurrency, Runnables and all of that kind of shit so it looks like I know what I&#039;m doing in Java but that makes the code five times more complicated and harder to understand.&lt;/dd&gt;
&lt;dt&gt;Take care of compiler warnings&lt;/dt&gt;
&lt;dd&gt;Analyze the warnings produced by the IDE when it starts up the target IDE and see what I can fix and what I should leave alone.&lt;/dd&gt;
&lt;dt&gt;Experiment with other SWI Prolog compiler options&lt;/dt&gt;
&lt;dd&gt;Try the -s option instead of the -c option and actually read the SWI documentation a little more closely.&lt;/dd&gt;
&lt;dt&gt;Fix remaining TODOs in code comments&lt;/dt&gt;
&lt;dd&gt;Probably I&#039;ll need to look at the good old Task List (ctrl+6) sometime. Jeez, it&#039;s like being married....&lt;/dd&gt;
&lt;dt&gt;Fix the *&amp;amp;$%!* coffee cup icon on my new Prolog projects&lt;/dt&gt;
&lt;dd&gt;Enough said. Although while I&#039;m at it I can see if there&#039;s anything else I can get rid of (or add) for new Prolog projects.&lt;/dd&gt;
&lt;dt&gt;Add license and digital certificate to GeeWhiz&lt;/dt&gt;
&lt;dd&gt;I should maybe make this an entry since a first glance at the docs available seemed less than promising.&lt;/dd&gt;
&lt;dt&gt;Find out how to create a target platform that is leaner for performance reasons&lt;/dt&gt;
&lt;dd&gt;Either that or buy a faster machine.&lt;/dd&gt;
&lt;/dl&gt;
&lt;br /&gt;
&lt;h4&gt;Additional Features That Could Be Added To GeeWhiz&lt;/h4&gt;
&lt;dl&gt;
&lt;dt&gt;Localize messages, strings, etc.&lt;/dt&gt;
&lt;dd&gt;Be a good world citizen and stick all messages etc. in Bundle&lt;/dd&gt;
&lt;dt&gt;Add help&lt;/dt&gt;
&lt;dd&gt;Add JavaHelp to the project. This might be another entry as well. It&#039;s pretty cool how it works, though....&lt;/dd&gt;
&lt;dt&gt;Make the static predicate visual model dynamic and refer back to source&lt;/dt&gt;
&lt;dd&gt;This is complicated by the fact that the predicate / clause relationship is not 1:1, but maybe light up all source clauses when a widget is selected....&lt;/dd&gt;
&lt;dt&gt;Add &lt;strong&gt;freemarker&lt;/strong&gt; support&lt;/dt&gt;
&lt;dd&gt;Oops, I was going to do that as part of the original project. Hopefully no one noticed.&lt;/dd&gt;
&lt;dt&gt;Interact with SWI Prolog via IOProvider Reader&lt;/dt&gt;
&lt;dd&gt;Just for fun we should try out the Reader in the output window.&lt;/dd&gt;
&lt;dt&gt;Create a satellite view for the modeler&lt;/dt&gt;
&lt;dd&gt;Make a satellite view of the diagram &lt;em&gt;a la&lt;/em&gt; Geertjan&#039;s example but preferably in a different window (popup?) as opposed to a sidebar.&lt;/dd&gt;
&lt;dt&gt;Add XPCE support&lt;/dt&gt;
&lt;dd&gt;Add support for SWI Prolog&#039;s buddy XPCE somehow. That would be a challenge, I bet... Wonder if it&#039;s Windows-compatible.&lt;/dd&gt;
&lt;/dl&gt;
&lt;br /&gt;
&lt;h4&gt;Either They&#039;re IDE Bugs Or I&#039;m Doing Something Wrong Dept.&lt;/h4&gt;
&lt;dl&gt;
&lt;dt&gt;On-again / off-again DataObject-dependent icons and menu items&lt;/dt&gt;
&lt;dd&gt;Find out once and for all if the above is me or the IDE. Then yell at the IDE people regardless.&lt;/dd&gt;
&lt;dt&gt;Wizards should be able to deal with icons already in the project directory&lt;/dt&gt;
&lt;dd&gt;For creating actions e.g. the wizard shouldn&#039;t give an error if the icon is already in the directory.&lt;/dd&gt;
&lt;dt&gt;Better reload support in &quot;Install / reload to target&quot;&lt;/dt&gt;
&lt;dd&gt;I shouldn&#039;t have to clean the project every damn time I retest. Look into security errors etc.&lt;/dd&gt;
&lt;/dl&gt;
&lt;br /&gt;
&lt;h4&gt;Areas For Further Research&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;NetBeans platforms and their creation&lt;/li&gt;
&lt;li&gt;Visual Library, especially the VMD part&lt;/li&gt;
&lt;li&gt;JavaHelp&lt;/li&gt;
&lt;li&gt;DataObjects, cookies, and their ilk&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;

 
    </content:encoded>

    <pubDate>Fri, 23 May 2008 15:18:12 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/11-guid.html</guid>
    
</item>
<item>
    <title>GeeWhiz Prolog - Part Seven - Adding An Option Panel</title>
    <link>http://hulles.supersized.org/archives/9-GeeWhiz-Prolog-Part-Seven-Adding-An-Option-Panel.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/9-GeeWhiz-Prolog-Part-Seven-Adding-An-Option-Panel.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=9</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=9</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;em&gt;&lt;p&gt;This is Part Seven, the eighth part of a series of entries describing an implementation of the Prolog language in the NetBeans IDE. &lt;/p&gt;
&lt;br/&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/2-GeeWhiz-Prolog-Part-Zero-About-the-Project.html&quot; alt=&quot;About the Project&quot;&gt;Part Zero, &quot;About The Project,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/3-GeeWhiz-Prolog-Part-One-Before-We-Start.html&quot; alt=&quot;Before We Start&quot;&gt;Part One, &quot;Before We Start,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/4-GeeWhiz-Prolog-Part-Two-Creating-A-File-Type.html&quot; alt=&quot;Creating A File Type&quot;&gt;Part Two, &quot;Creating A File Type,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/5-GeeWhiz-Prolog-Part-Three-Adding-Language-Support.html&quot; alt=&quot;Adding Language Support&quot;&gt;Part Three, &quot;Adding Language Support,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html&quot; alt=&quot;A Visual Prolog Modeler&quot;&gt;Part Four, &quot;A Visual Prolog Modeler&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html&quot; alt=&quot;Adding The Compiler&quot;&gt;Part Five, &quot;Adding The Compiler&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/8-GeeWhiz-Prolog-Part-Six-Creating-Prolog-Projects.html&quot; alt=&quot;Creating Prolog Projects&quot;&gt;Part Six, &quot;Creating Prolog Projects&quot; is here.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Our Prolog IDE is quickly maturing into a comfortable, fun and feature-rich programming environment. But if you&#039;re like me -- and I hope for your sake you are not -- you&#039;ve been laying awake at night, sweating, thinking to yourself, &lt;/p&gt;
&lt;blockquote&gt;&quot;Gee whiz! I created this great Prolog IDE but I totally ruined it when I hard-coded the compiler command stuff into the project (see &lt;a href=&quot;http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html&quot; alt=&quot;Adding The Compiler&quot;&gt;Part Five, &quot;Adding The Compiler&quot;&lt;/a&gt;). Now I can&#039;t make it into an NBM and distribute it and have everybody in the world use it and love it and have somebody write an article for NetBeans.org called &#039;Meet A NetBeans Module Writer: Hulles&#039; with my picture in it and everything.&quot;&lt;/blockquote&gt;
&lt;p&gt;Well, we all need our sleep, so lay awake no longer. This time we&#039;re going to add an IDE-level Prolog options screen where we can set the compiler command and arguments outside of our code and have it retained between sessions. We&#039;re also going to clean up some code while we&#039;re at it so our project is a little more compatible with the NetBeans IDE -- a &quot;better NetBeans citizen,&quot; as they say.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;This entry is partially based on a Geertjan article in NetBeans called &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/platform.netbeans.org/tutorials/60/nbm-options.html&#039;);&quot; href=&quot;http://platform.netbeans.org/tutorials/60/nbm-options.html&quot; title=&quot;NetBeans link&quot;&gt;&quot;NetBeans Options Window Module Tutorial&quot;&lt;/a&gt;. I recommend checking it out prior to doing this entry if you feel so inclined; he gives you more background than I give you here. And thanks to the author for that tutorial and all the other fine NetBeans articles he has done.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Adding An Options Panel&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;First off we&#039;re going to start up the New Options Wizard. Right-click on your GeeWhiz project and select &quot;New&quot; &quot;Other&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:97 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-1a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Select the &quot;Module Development&quot; category and choose &quot;Options Panel&quot;, then click &quot;Next&quot;. On the next screen of the wizard we&#039;re going to create a tab for Prolog in the &quot;Miscellaneous&quot; section of the &quot;Tools/Options&quot; menu.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-1b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:98 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-1b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Select &quot;Create Miscellaneous Panel&quot; then enter &quot;Prolog&quot; for the title. Type &quot;Prolog project options&quot; for the tooltip text and hit &quot;Next&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-1c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:99 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-1c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

The next screen should come up already filled in for you, but check and make sure the project is &quot;GeeWhiz Prolog&quot;, the class name prefix is &quot;Geewhiz&quot;, and the package name is filled in correctly (&quot;org.myorg.geewhiz&quot;). Then click &quot;Finish&quot; and let the wizard generate the files.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Now we&#039;re going to take the panel that the wizard created and modify it for our own nefarious purposes. Open &quot;GeewhizPanel.java&quot; in design mode and from the Swing palette add a panel that fills the frame, then add two labels and two text fields to the panel, as in the screenshot.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-2a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:100 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-2a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Rename the top text field by right-clicking it and selecting &quot;Change Variable Name...&quot;. Call it &quot;compilerName&quot;. Add a tooltip to it in Properties that says &quot;Enter the command to invoke the compiler, e.g. &quot;swipl&quot;&quot;. Rename the bottom text field to &quot;compilerArgs&quot; in the same way and add a tooltip that says &quot;Enter arguments to the compiler command, e.g. &quot;-c -r&quot;&quot;. When you&#039;re satisfied, switch to source view and change the load and store methods to:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
    void load() {
        compilerName.setText(NbPreferences.forModule(GeewhizPanel.class).
                get(&quot;compilerName&quot;, &quot;swipl&quot;));        
        compilerArgs.setText(NbPreferences.forModule(GeewhizPanel.class).
                get(&quot;compilerArgs&quot;, &quot;-c&quot;));        
    }

    void store() {
        NbPreferences.forModule(GeewhizPanel.class).put(&quot;compilerName&quot;, 
                compilerName.getText());
        NbPreferences.forModule(GeewhizPanel.class).put(&quot;compilerArgs&quot;, 
               compilerArgs.getText());
    }
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;What we&#039;re doing here is loading and storing the two data we need for our compiler, the compiler command and arguments string, in NetBeans Preferences. It may be necessary at some point to add environment and working directory information here, but for now we&#039;ll just leave it at the command and arguments.&lt;/p&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-2b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:101 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-2b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;Save and close the GeewhizPanel class.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Modifying The Compiler Class&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Now we need to change our PrologCompiler class to use the NbPreferences we created in the Options panel. I went through several iterations of changes and testing with this class, and here is the final version (as if any programming code was ever final). &lt;em&gt;Note: if you&#039;ve made any changes to the class yourself from the version we created earlier, you should save your old version of PrologCompiler.java prior to making these changes.&lt;/em&gt; Whenever you&#039;re ready, change the class definition to the one listed below:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
public class PrologCompiler {
    private DataObject dataObject;
    private String fileName;
    private String compilerName;
    private String compilerArgs;
    
    public PrologCompiler() {
        Preferences pref;
        
        this.dataObject = null;
        pref = NbPreferences.forModule(GeewhizPanel.class);
        this.compilerName = pref.get(&quot;compilerName&quot;, &quot;&quot;);
        this.compilerArgs = pref.get(&quot;compilerArgs&quot;, &quot;&quot;);
        
        pref.addPreferenceChangeListener(new PreferenceChangeListener() {
            public void preferenceChange(PreferenceChangeEvent evt) {
                if (evt.getKey().equals(&quot;compilerName&quot;)) {
                    compilerName = (evt.getNewValue());
                } else if (evt.getKey().equals(&quot;compilerArgs&quot;)) {
                    compilerArgs = (evt.getNewValue());
                }
            }
        });
    }
    
    public void compileDataObject(DataObject dObj) {
        ProcessBuilder procBuilder;
        Process process;
        List&amp;lt;String&amp;gt; cmd;
        Map&amp;lt;String, String&amp;gt; env;
        String line;
        InputOutput io;
        OutputWriter outputWriter;
        SaveCookie sCookie;

        
        // set DataObject and file name
        this.dataObject = dObj;
        File file = FileUtil.toFile(dObj.getPrimaryFile());
        this.fileName = file.getAbsolutePath();
        
        // save file first if it&#039;s been modified
        sCookie = dObj.getCookie (SaveCookie.class);
        if (sCookie != null) {
            try {
                sCookie.save();
                StatusDisplayer.getDefault().setStatusText(&quot;Save finished&quot;);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        
        // get an output window tab
        io = IOProvider.getDefault().getIO(&quot;Prolog&quot;, false);
        io.select();
        outputWriter = io.getOut();

        // first see if we have a compiler available
        if (this.compilerName.isEmpty()) {
            outputWriter.println(&quot;You need to set up the compiler first.&quot;);
            outputWriter.print(&quot;In the main menu go to &#039;Tools / Options&quot;);
            outputWriter.println(&quot;/ Miscellaneous / Prolog&#039;.&quot;);
            whiteLines(outputWriter);
            outputWriter.close();
            return;
        }

        // construct the SWI Prolog process command
        cmd = new ArrayList&amp;lt;String&amp;gt;();
        cmd.add(this.compilerName);
        cmd.add(this.compilerArgs);
        cmd.add(fileName);
        
        procBuilder = new ProcessBuilder(cmd);
        procBuilder.redirectErrorStream(true);
        try {
            process = procBuilder.start();
            InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            // TODO: might want to clear the output window first...
            outputWriter.printf(&quot;Output of running %s is:\n\n&quot;,
                        commandString(cmd));
            while ((line = br.readLine()) != null) {
                if (lineIsNotable(line)) {
                    outputWriter.println(line, listener);
                } else {
                    outputWriter.println(line);
                }
            }
        } catch (IOException ex) {
            outputWriter.print(&quot;Error occurred running Prolog compiler. &quot;);
            outputWriter.println(&quot;Check options.&quot;);
            outputWriter.print(&quot;In the main menu go to &#039;Tools / Options&quot;);
            outputWriter.println(&quot;/ Miscellaneous / Prolog&#039;.&quot;);
            outputWriter.printf(&quot;Command string is %s.\n&quot;, commandString(cmd));
     //       Exceptions.printStackTrace(ex);
        } finally {
            whiteLines(outputWriter);
            outputWriter.close();
        }
    }

    private OutputListener listener = new OutputListener() {
        public void outputLineAction(OutputEvent ev) {
            String outputLine;
            Line editorLine;
            LineCookie lCookie;
            int lineNumber;
            int columnNumber;
            
            outputLine = ev.getLine();
            lineNumber = parseLineNumber(outputLine);
            columnNumber = parseColumnNumber(outputLine);
            lCookie = dataObject.getCookie (LineCookie.class);
            editorLine = lCookie.getLineSet ().getOriginal (lineNumber-1);
            editorLine.show (Line.SHOW_GOTO, columnNumber);

            StatusDisplayer.getDefault().setStatusText(&quot;Fix me!&quot;);
        }
        public void outputLineSelected(OutputEvent ev) {
            // Let&#039;s not do anything special.
        }
        public void outputLineCleared(OutputEvent ev) {
            // Leave it blank, no state to remove.
        }

    };

    
    private boolean lineIsNotable(String line) {
        boolean result = false;
        
        if (line.startsWith(&quot;Warning:&quot;) || line.startsWith(&quot;ERROR:&quot;)) {
            result = true;
        }
        return result;
    }
    
/*
 * SAMPLE SWI PROLOG LINES:
ERROR: /home/.../sieve.pro:16:0: Syntax error: Operator expected
Warning: (/home/.../sieve.pro:18): Singleton variables: [P]
*/
    
    private int parseLineNumber(String line) {
        int fpos;
        int startpos;
        int lineNumber;
        Character ch;
        StringBuffer numBuf;
        
        fpos = line.indexOf(this.fileName);
        // assuming there are no colons in file name!
        startpos = line.indexOf(&quot;:&quot;, fpos);
        if (startpos == -1) {
            // lineNumber is converted to lineNumber - 1
            //     this causes an exception in caller if this is 0
            //     so return 1 instead
            return 1;
        }
        numBuf = new StringBuffer();
        for (int i = startpos+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                numBuf.append(ch);
            } else {
                break;
            }
        }
        lineNumber = Integer.parseInt(numBuf.toString());
        return lineNumber;
    }
    
    private int parseColumnNumber(String line) {
        int fpos;
        int startpos;
        int colNumber;
        Character ch;
        StringBuffer numBuf;
        int colstart = -1;
        
        fpos = line.indexOf(this.fileName);
        // assuming there are no colons in file name!
        startpos = line.indexOf(&quot;:&quot;, fpos);
        if (startpos == -1) {
            return 0;
        }
        for (int i = startpos+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                // skip line number
            } else {
                colstart = i;
                break;
            }
        }
        if ((colstart == -1) || (line.charAt(colstart) != &#039;:&#039;)) {
            return 0;
        }
        numBuf = new StringBuffer();
        for (int i = colstart+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                numBuf.append(ch);
            } else {
                break;
            }
        }
        colNumber = Integer.parseInt(numBuf.toString());
        return colNumber;
    }
    
    private void whiteLines(OutputWriter ow) {
        final int limit = 3;
        
        for(int i = 0; i &amp;lt; limit; i++) {
            ow.println();
        }
    }
    
    private String commandString(List&amp;lt;String&amp;gt; cmds) {
        StringBuffer sBuf;
        
        sBuf = new StringBuffer();
        for (String cmd : cmds) {
            sBuf.append(cmd);
            sBuf.append(&#039; &#039;);
        }
        // leave extra space on the end
        return sBuf.toString();
    }
}
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Actually, rather a lot has changed. Notice in the constructor that we are now getting the compiler command and arguments from NbPreferences and starting a listener to see if they change. Actually, the listener may be overkill for this application but as I mentioned above we&#039;re trying to be better NetBeans citizens so let&#039;s leave it in just in case we have a very quick typist on our hands.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Also notice that now we are checking for a SaveCookie before we start the compilation. If one exists, and it will if our source file has been modified since the last save, we grab it and use it to save the file prior to compiling it. I love how easy that is in NetBeans. We follow the NetBeans Java example of not asking prior to doing the save; we just go ahead and do it.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Note that we also are adding a couple helper methods to clean up our code (and the output) a little bit. White space rocks. And we&#039;re adding more cleanup -- we are finally closing the OutputWriter in our class.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Since we opened up the compiler command and arguments to user input, now we have to do some reality checks on the data prior to using it. First we check to make sure the NbPreference is there for the compiler command and issue an error if it is not. (The command arguments should be optional.) The compiler command will &lt;strong&gt;not&lt;/strong&gt; be there if the user has not set up the compiler in our new options panel so we firmly order her/him to go to the options panel and set it up right the hell now. Hmph. The nerve.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;We also changed the try/catch for the compiler invocation, since now we&#039;re executing whatever the user typed in for a command and arguments. Instead of doing a stack trace we&#039;re issuing an error message in the catch, since 

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opt-4d.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:102 --&gt;&lt;img width=&quot;90&quot; height=&quot;45&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opt-4d.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

is not considered good user feedback in most circles. Never mind how I got the screenshot, why do you think I changed it? Of course I left the stack trace in place but commented out, since no good Java programmer feels completely comfortable about a catch statement without a stack trace laying around somewhere.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;I think that about covers the changes. Let&#039;s try it out. But before we do that, you might want to grab a new PrologAST from the archive to this article. I modified it to not print all the debugging information unless a constant is set, and if printing is requested to not keep the OutputWriter tied up quite so long. Good citizenship again, but not worth including the source code in this article.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Testing The Option Panel And The Compiler&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;You know the drill -- clean and build the GeeWhiz project then install it to the target IDE. &lt;em&gt;Don&#039;t&lt;/em&gt; go into the options menu yet. Open up the &quot;Algorithms&quot; project (!) and open sieve.pro. Try to compile it with the menu bar button. You should get an error.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opta-5a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:103 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opta-5a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Next, from the main menu, select &quot;Tools&quot; &quot;Options&quot;, then click the &quot;Miscellaneous&quot; tab then the &quot;Prolog&quot; tab.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opta-5b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:104 --&gt;&lt;img width=&quot;90&quot; height=&quot;62&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opta-5b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Our options panel should appear with the default values from our load statements in GeewhizPanel. Click &quot;OK&quot;. Now try compiling sieve.pro again. You should get a normal compilation.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opta-5c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:105 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opta-5c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Now go back into our option panel and change the values to something invalid for your compiler and platform, like :

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opta-5d.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:106 --&gt;&lt;img width=&quot;90&quot; height=&quot;62&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opta-5d.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Click &quot;OK&quot; to save them, then try compiling again. You should get an error.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/opta-5e.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:107 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/opta-5e.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

You don&#039;t need to change the options back since they&#039;ll go away once the target IDE is destroyed in our clean and build. However, before you quit testing you should make sure you can still create a diagram with the modified PrologAST class without printing any text in the Prolog output tab if you installed the class from this article&#039;s archives. Then you can quit.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;So now GeeWhiz is back to being platform- and compiler-independent and it&#039;s a little easier on the NetBeans enviroment. Now maybe we can all go get some sleep. Next time we&#039;ll create a NetBeans module (NBM) file for sharing with others, a fairly trivial task, and sum up what we&#039;ve accomplished so far. Zzzzzz....&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Files From This Entry&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partseven.tar.gz&#039;&gt;geewhiz_partseven.tar.gz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a onclick=&quot;javascript:urchinTracker(&#039;/download/uploads/geewhiz/geewhiz_partseven.zip&#039;);&quot; href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partseven.zip&#039;&gt;geewhiz_partseven.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;br /&gt;

 
    </content:encoded>

    <pubDate>Thu, 22 May 2008 17:05:13 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/9-guid.html</guid>
    
</item>
<item>
    <title>GeeWhiz Prolog - Part Six - Creating Prolog Projects</title>
    <link>http://hulles.supersized.org/archives/8-GeeWhiz-Prolog-Part-Six-Creating-Prolog-Projects.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/8-GeeWhiz-Prolog-Part-Six-Creating-Prolog-Projects.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=8</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=8</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;em&gt;This is Part Six, the seventh part of a series of entries describing an implementation of the Prolog language in the NetBeans IDE. 
&lt;br/&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/2-GeeWhiz-Prolog-Part-Zero-About-the-Project.html&quot; alt=&quot;About the Project&quot;&gt;Part Zero, &quot;About The Project,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/3-GeeWhiz-Prolog-Part-One-Before-We-Start.html&quot; alt=&quot;Before We Start&quot;&gt;Part One, &quot;Before We Start,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/4-GeeWhiz-Prolog-Part-Two-Creating-A-File-Type.html&quot; alt=&quot;Creating A File Type&quot;&gt;Part Two, &quot;Creating A File Type,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/5-GeeWhiz-Prolog-Part-Three-Adding-Language-Support.html&quot; alt=&quot;Adding Language Support&quot;&gt;Part Three, &quot;Adding Language Support,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html&quot; alt=&quot;A Visual Prolog Modeler&quot;&gt;Part Four, &quot;A Visual Prolog Modeler&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html&quot; alt=&quot;Adding The Compiler&quot;&gt;Part Five, &quot;Adding The Compiler&quot; is here.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;So far we&#039;ve cobbled together a pretty decent Prolog IDE within the NetBeans environment. As far as features, it has... well, you can review the previous articles in the series yourself but it has a lot of Cool Stuff. Now we&#039;re going to create a new project template so when you want to start working on a new Prolog project you don&#039;t have to call it a Java class library or a web application just to be able to create new Prolog source files.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Create A New Project Template&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;First we need to create a sample project to use in the new project template wizard. This project should have what just what we need when we start a new Prolog project and no more. Since we&#039;re only working with text source files, that&#039;s pretty much all the project needs. We&#039;ll just copy one source file into the project since both Nature and Hulles abhor a vacuum. In the main menu, select &quot;File&quot; &quot;New Project&quot; and create yourself a new Java class library project called, appropriately enough,  &quot;NewProject&quot;.&lt;/p&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:85 --&gt;&lt;img width=&quot;90&quot; height=&quot;55&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-1a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;Find a copy of &lt;strong&gt;sieve.pro&lt;/strong&gt; in your target IDE directory and copy it into the src folder of NewProject. If you would prefer, you can extract a copy from the archive files at the end of this article.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Now we&#039;re going to pare down the project as much as we can, which isn&#039;t much at this point. Right-click on NewProject and select &quot;Properties&quot;. In &quot;Categories&quot; select &quot;Libraries&quot;, then click the &quot;Compile Tests&quot; tab. Delete the test libraries that are there.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-1b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:86 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-1b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Click &quot;OK&quot; to close the properties window. Now we have a simple project we can use as a base for creating new Prolog projects. Time to create our new project template. Right-click the GeeWhiz project and select &quot;New&quot; &quot;Project Template...&quot;. In the first screen of the wizard select &quot;NewProject&quot;. 

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-2a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:87 --&gt;&lt;img width=&quot;90&quot; height=&quot;64&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-2a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Click &quot;Next&quot;. On the next screen of the wizard, enter &quot;NewProject&quot; for the template name, &quot;Prolog Application&quot; for the display name, select &quot;Other&quot; for the category, and make sure the package is correctly filled in.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-2c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:88 --&gt;&lt;img width=&quot;90&quot; height=&quot;88&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-2c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Once everything is correct, click &quot;Finish&quot;.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Now we&#039;re going to customize our new project template a little bit. Edit &quot;NewProjectDescription.html&quot; and change the description to simply &quot;Prolog project&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-3a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:89 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-3a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Save and close the file. Open the layer.xml file and traverse &quot;this layer&quot; down to &quot;Templates&quot; &quot;Project&quot; &quot;Other&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-3b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:90 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-3b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Right-click on &quot;Prolog Application&quot; and select &quot;Pick Icon...&quot;. Navigate to your package source folder and select &quot;prolog-star.png&quot;, the dreaded Black Star of Prolog.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-3c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:91 --&gt;&lt;img width=&quot;90&quot; height=&quot;49&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-3c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Click &quot;OK&quot; and you&#039;re done. You can now delete the &quot;NewProject&quot; project because we won&#039;t need it anymore. The necessary stuff from &quot;NewProject&quot; was zipped into our &quot;GeeWhiz&quot; project by the new project template wizard.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Testing The New Template&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Our new Prolog project template should now be ready to test. Clean and build your main project and install it to the Target IDE. Once your &quot;personal domain&quot; is created, in the main menu select &quot;File&quot; &quot;New Project&quot; and you should see our new Prolog project option, complete with BSofP icon.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-4a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:92 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-4a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;
Select &quot;Prolog Application&quot; and fill in the necessary fields, calling your new project &quot;Algorithms&quot; in honor of our two hard-working sample Prolog programs, fib1.pro and sieve.pro.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-4b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:93 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-4b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

Check out &quot;Algorithms&quot; and note that &quot;sieve.pro&quot; is include in the default package of our new project. If you want to be really loyal, copy &lt;strong&gt;fib1.pro&lt;/strong&gt; into our new project and delete the &quot;BraveNewWorld&quot; project since we won&#039;t need it anymore.&lt;/p&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/npp-4c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:94 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/npp-4c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;While we&#039;re here, note also that there is a &lt;strong&gt;disturbing Java coffee cup icon&lt;/strong&gt; on our new Prolog project. There &lt;em&gt;is&lt;/em&gt; a way to change that, but that procedure is beyond the scope of this how-to series. This is because I have no idea what the procedure is. If you do, please let me know. &lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;There, wasn&#039;t that easy? Now we have a way to create a Prolog project as a home for our precious Prolog source code. Next we&#039;ll do some housework in GeeWhiz and make it a &quot;good NetBeans IDE citizen&quot; (or at least a better one). In the process we&#039;ll make GeeWhiz Prolog platform- and compiler-independent once again. (It was until the last entry when we added the compiler.) Until next time.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Files From This Entry&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partsix.tar.gz&#039;&gt;geewhiz_partsix.tar.gz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a onclick=&quot;javascript:urchinTracker(&#039;/download/uploads/geewhiz/geewhiz_partsix.zip&#039;);&quot; href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partsix.zip&#039;&gt;geewhiz_partsix.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;br /&gt;


 
    </content:encoded>

    <pubDate>Thu, 22 May 2008 13:45:23 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/8-guid.html</guid>
    
</item>
<item>
    <title>GeeWhiz Prolog - Part Five - Adding The Compiler</title>
    <link>http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/7-GeeWhiz-Prolog-Part-Five-Adding-The-Compiler.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=7</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=7</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;em&gt;This is Part Five, the sixth part of a series of entries describing an implementation of the Prolog language in the NetBeans IDE. 
&lt;br/&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/2-GeeWhiz-Prolog-Part-Zero-About-the-Project.html&quot; alt=&quot;About the Project&quot;&gt;Part Zero, &quot;About The Project,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/3-GeeWhiz-Prolog-Part-One-Before-We-Start.html&quot; alt=&quot;Before We Start&quot;&gt;Part One, &quot;Before We Start,&quot; is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/4-GeeWhiz-Prolog-Part-Two-Creating-A-File-Type.html&quot; alt=&quot;Creating A File Type&quot;&gt;Part Two, &quot;Creating A File Type,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/5-GeeWhiz-Prolog-Part-Three-Adding-Language-Support.html&quot; alt=&quot;Adding Language Support&quot;&gt;Part Three, &quot;Adding Language Support,&quot; is here.&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html&quot; alt=&quot;A Visual Prolog Modeler&quot;&gt;Part Four, &quot;A Visual Prolog Modeler&quot; is here.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Up to this point we&#039;ve created a Prolog editor within the NetBeans IDE with built-in syntax highlighting, navigation, a visual modeler, and some other stuff that I forget but that&#039;s probably pretty cool. Now we&#039;re going to add in-place compilation so we don&#039;t need to switch between NetBeans and whatever Prolog compiler we&#039;re using just to fix syntax errors and such.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;In this entry I&#039;ll be using &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/www.swi-prolog.org/&#039;);&quot; href=&quot;http://www.swi-prolog.org/&quot; title=&quot;SWI Prolog home page&quot;&gt;SWI Prolog&lt;/a&gt; as my Prolog compiler. It&#039;s a free, robust open-source compiler that runs on multiple platforms including, probably, yours. One thing it does &lt;em&gt;not&lt;/em&gt; have, however, is a feature-rich IDE -- hence this project. When we&#039;re done with this segment, we&#039;ll be able to compile our Prolog source code directly from the NetBeans IDE and hotlink (whatever that means) the error lines back to our source code. In other words, it will function much like the Java compilation process within NetBeans that we all know and love.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;By the way, if you currently use a different Prolog compiler, don&#039;t worry. Once we&#039;re done here it should be pretty obvious how to adapt this project to incorporate your favorite compiler as long as you can run it from a terminal command line. In fact part of the reason I&#039;m writing this how-to is to allow you to adapt &lt;strong&gt;ANY&lt;/strong&gt; language to the NetBeans IDE. I&#039;m trying to assemble the knowledge that&#039;s scattered around the NetBeans universe in one place so that this series of articles gives you the ability to quickly and dirtily add your favorite language to the NetBeans IDE. We&#039;ll work on the &quot;dirtily&quot; part later; for now our goal is &lt;em&gt;results&lt;/em&gt;, baby.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Adding Compiler Support&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Adding compiler support to GeeWhiz turns out to be surprisingly easy. It&#039;s easy if you know where to look for info, that is. It took me for-effing-ever to find the information I needed to do this, but once I did, implementing support for an external compiler turned out to be almost trivial. But I digress. The first thing we need to do is create an action in our project to invoke the compiler. Right-click on our GeeWhiz project and select &quot;New&quot; &quot;Action&quot;.&lt;/p&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:77 --&gt;&lt;img width=&quot;90&quot; height=&quot;64&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-1a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;In the first screen of the New Action Wizard, once again select &quot;Conditionally Enabled&quot; and &quot;User Selects One Node&quot;. Set the cookie class to &quot;DataObject&quot; since we want to only compile Prolog source files with our compiler. Hit the &quot;Next&quot; button.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-1b.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:78 --&gt;&lt;img width=&quot;90&quot; height=&quot;85&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-1b.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

On this wizard screen select &quot;File&quot; for a category (just for something different; we chose &quot;Other&quot; for our &quot;ShowDiagram&quot; action). &lt;em&gt;(I&#039;ve always wondered why it takes so long for this window to come up on my machine. I suspect that this is the place where NetBeans is sending encrypted information about my unspeakable habits to our shadowy overlords.)&lt;/em&gt; Uncheck &quot;Global Menu Item&quot; and check &quot;Global Toolbar Button&quot; (again, for something different). We&#039;re going to stick our toolbar button at the very end of the Build toolbar so select &quot;Build&quot; for the toolbar and &quot;Profile Main Project... - HERE&quot; as the position. Click &quot;Next&quot;.&lt;/p&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-1c.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:79 --&gt;&lt;img width=&quot;90&quot; height=&quot;85&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-1c.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;On this screen, enter &quot;CompileProlog&quot; for a class name and &quot;Compile Prolog Program&quot; for a display name. For icons, you&#039;ll need both a 16x16 and 24x24 icon in the same directory, called (in our case) compile16.png and compile24.png, otherwise the wizard will grumpily issue error messages until you do. You can use these if you&#039;d like, another modified Black Star of Prolog. &lt;!-- s9ymdb:73 --&gt;&lt;img width=&quot;16&quot; height=&quot;16&quot; style=&quot;float: left; border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/compile16.png&quot; alt=&quot;&quot;  /&gt;  &lt;!-- s9ymdb:74 --&gt;&lt;img width=&quot;24&quot; height=&quot;24&quot; style=&quot;float: left; border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/compile24.png&quot; alt=&quot;&quot;  /&gt; Right-click on them in your browser and save them to a directory that is not your project directory and let the wizard copy them. Fill in the path and file name of the 16x16 icon in the icon field in the wizard. Make sure your package node (&quot;org.myorg.geewhiz&quot;) is filled in in the package field and click &quot;Finish&quot;.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Note: in the last screenshot ignore the GeeWhiz2 reference. I didn&#039;t make screenshots of this process the first time around, probably because I didn&#039;t expect it to work the first time! I thought I&#039;d have to do 8 or 9 trials to get it right like I did for the other stuff in this project. Gee whiz, I must be learning something....&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Once the wizard creates our new action, you can close the icon files in the editor and add the following lines to the &lt;strong&gt;CompileProlog&lt;/strong&gt; class, where it says &quot;TODO: use DataObject&quot;:
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
        PrologCompiler compiler = new PrologCompiler();
        compiler.compileDataObject(dataObject);
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-2a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:80 --&gt;&lt;img width=&quot;90&quot; height=&quot;61&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-2a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

&lt;p&gt;Save and close the file. Great. We have a toolbar action, now all we need to do is write a PrologCompiler class. So let&#039;s do that.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Create a new Java class called &quot;PrologCompiler&quot; and replace the empty class with:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
public class PrologCompiler {
    DataObject dataObject;
    String fileName;
    
    public PrologCompiler() {
        this.dataObject = null;
    }
    
    public void compileDataObject(DataObject dObj) {
        ProcessBuilder procBuilder;
        Process process;
        Map&amp;lt;String, String&amp;gt; env;
//        File currDir;
        List&amp;lt;String&amp;gt; cmd;
        String line;
        InputOutput io;
        OutputWriter outputWriter;

        // TODO: should save file first if it&#039;s been modified
        
        // set DataObject and file name
        this.dataObject = dObj;
        File file = FileUtil.toFile(dObj.getPrimaryFile());
        fileName = file.getAbsolutePath();
        
        // get an output window tab
        io = IOProvider.getDefault().getIO(&quot;Prolog&quot;, false);
        io.select();
        outputWriter = io.getOut();

        // construct the SWI Prolog process command
        cmd = new ArrayList&amp;lt;String&amp;gt;();
        cmd.add(&quot;swipl&quot;);
        cmd.add(&quot;-c&quot;);
        cmd.add(fileName);
        
        procBuilder = new ProcessBuilder(cmd);
        procBuilder.redirectErrorStream(true);
        // also s/b able to merge it into OutputWriter
//        env = procBuilder.environment();
//        env.put(&quot;VAR1&quot;, &quot;myValue&quot;);
//        env.remove(&quot;OTHERVAR&quot;);
//        env.put(&quot;VAR2&quot;, env.get(&quot;VAR1&quot;) + &quot;suffix&quot;);
//        currDir = procBuilder.directory();
//        if (currDir != null) {
//            System.out.printf(&quot;Current directory is %s.&quot;, currDir.toString());
//        }
//        procBuilder.directory(new File(&quot;myDir&quot;));
        try {
            process = procBuilder.start();
            InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            // TODO: might want to clear the output window first...
            outputWriter.printf(&quot;Output of running %s is:\n\n&quot;, cmd.toString());
            while ((line = br.readLine()) != null) {
                outputWriter.println(line);
            }
            // TODO: close outputwriter
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
}
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;What we want this to do is invoke the SWI Prolog compiler with our source file, the name of which we retrieved from our trusty Prolog DataObject. We&#039;re using the IOProvider/OutputWriter we saw last time to write the output to the Output tab, just like a real adult language module does. We&#039;re also using ProcessBuilder to build a Process so we can execute an external command.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;Just a couple of other things worth mentioning about the above class: one is that I left in some comments showing how to access the environment and change the working directory, just in case you need the info to make your compiler work. Also, note that the command line I used is for the Linux version of SWI Prolog. If you run on another platform, you&#039;ll probably need to change this. For example, I believe Windows uses &quot;plwin&quot;. See the &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/www.swi-prolog.org/&#039;);&quot; href=&quot;http://www.swi-prolog.org/&quot; title=&quot;SWI Prolog home page&quot;&gt;SWI Prolog&lt;/a&gt; site for more information.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Testing The First Version&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;So let&#039;s try it: clean and build your main project and install to the target IDE. Open up the BraveNewWorld project. Wait until the excitement dies down. Open up sieve.pro. Add a line somewhere in the program that says:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
	gruesome(ugly error).
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;This introduces an error in our otherwise nearly pristine Prolog program. Save sieve.pro. Find our new compiler button on the toolbar and click it.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-3a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:81 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-3a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

At this point my original notes say &quot;holy shit it worked!&quot; As indeed it did, the first time. &lt;em&gt;Nothing&lt;/em&gt; works the first time, ever. Imagine my elation. If you look at the &quot;Prolog&quot; output tab (!), you&#039;ll see the gruesome ugly error we introduced does indeed give us an error in the compiler output. Also note in passing that our syntax parser did flag our gruesome ugly error statement as an error. Heh heh.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;The compiler also gives us a warning that there is a singleton variable in one of the clauses. This means that the variable &quot;P&quot; in the statement &quot;remove(P,[],[]).&quot; isn&#039;t used. In Prolog, instead of using a named variable here you should use an anonymous variable, the underscore. If you want you can change the statement to read &quot;remove(_,[],[]).&quot; and recompile it to see that the warning goes away. When you&#039;re done muttering &quot;Gee whiz!&quot; you can close the target IDE.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Add Hotlinks (Whatever They Are)&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Now we&#039;re going to add hyperlinks to our compiler output so when you click an error line in the output you are magically transported to the source code at the point of the error. I know, you&#039;re saying &quot;Gee whiz!&quot; to yourself again. Just wait....&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;In trying to add this feature, I knew exactly what I wanted to do but I really wasn&#039;t sure how to accomplish it. Until, that is, I found an article called &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/platform.netbeans.org/articles/nbm_interview_jens.html&#039;);&quot; href=&quot;http://platform.netbeans.org/articles/nbm_interview_jens.html&quot; title=&quot;NetBeans link&quot;&gt;&quot;Meet A NetBeans Module Writer: Jens Trapp&quot;&lt;/a&gt;. In the article is a code snippet that does exactly what I wanted to do in about three lines of code! Thank you Mr. Trapp; may the rest of your days be happy ones. Who knew there was a LineCookie that plunked you right down in the middle of the source code editor? Probably the people who RTFD, that&#039;s who.... But for the rest of us there&#039;s Hulles.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;So now we&#039;re going to change our PrologCompiler class to &quot;hotlink&quot; our compiler code to our source code. Open the class file and replace the class with this:&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre&gt;
public class PrologCompiler {
    DataObject dataObject;
    String fileName;
    
    public PrologCompiler() {
        this.dataObject = null;
    }
    
    public void compileDataObject(DataObject dObj) {
        ProcessBuilder procBuilder;
        Process process;
        Map&amp;lt;String, String&amp;gt; env;
        List&amp;lt;String&amp;gt; cmd;
        String line;
        InputOutput io;
        OutputWriter outputWriter;

        // TODO: should save file first if it&#039;s been modified
        
        // set DataObject and file name
        this.dataObject = dObj;
        File file = FileUtil.toFile(dObj.getPrimaryFile());
        fileName = file.getAbsolutePath();
        
        // get an output window tab
        io = IOProvider.getDefault().getIO(&quot;Prolog&quot;, false);
        io.select();
        outputWriter = io.getOut();

        // construct the SWI Prolog process command
        cmd = new ArrayList&amp;lt;String&amp;gt;();
        cmd.add(&quot;swipl&quot;);
        cmd.add(&quot;-c&quot;);
        cmd.add(fileName);
        
        procBuilder = new ProcessBuilder(cmd);
        procBuilder.redirectErrorStream(true);
        // also s/b able to merge it into OutputWriter
        try {
            process = procBuilder.start();
            InputStream is = process.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            // TODO: might want to clear the output window first...
            outputWriter.printf(&quot;Output of running %s is:\n\n&quot;, cmd.toString());
            while ((line = br.readLine()) != null) {
                if (lineIsNotable(line)) {
                    outputWriter.println(line, listener);
                } else {
                    outputWriter.println(line);
                }
            }
            // TODO: close outputwriter
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private OutputListener listener = new OutputListener() {
        public void outputLineAction(OutputEvent ev) {
            String outputLine;
            Line editorLine;
            LineCookie lCookie;
            int lineNumber;
            int columnNumber;
            
            outputLine = ev.getLine();
            lineNumber = parseLineNumber(outputLine);
            columnNumber = parseColumnNumber(outputLine);
//          System.out.printf(&quot;Showing line %d column %d.\n&quot;, 
//                      lineNumber, columnNumber);
            lCookie = (LineCookie) dataObject.getCookie (LineCookie.class);
            editorLine = lCookie.getLineSet ().getOriginal (lineNumber-1);
            editorLine.show (Line.SHOW_GOTO, columnNumber);

            StatusDisplayer.getDefault().setStatusText(&quot;Fix me!&quot;);
        }
        public void outputLineSelected(OutputEvent ev) {
            // Let&#039;s not do anything special.
        }
        public void outputLineCleared(OutputEvent ev) {
            // Leave it blank, no state to remove.
        }

    };
    
    private boolean lineIsNotable(String line) {
        boolean result = false;
        
        if (line.startsWith(&quot;Warning:&quot;) || line.startsWith(&quot;ERROR:&quot;)) {
            result = true;
        }
        return result;
    }
    
/*
SAMPLE SWI PROLOG ERROR AND WARNING LINES:
ERROR: /home/.../bravenewworld/sieve.pro:16:0: Syntax error: Operator expected
Warning: (/home/.../bravenewworld/sieve.pro:18): Singleton variables: [P]
*/
    
    private int parseLineNumber(String line) {
        int fpos;
        int startpos;
        int lineNumber;
        Character ch;
        StringBuffer numBuf;
        
        fpos = line.indexOf(this.fileName);
		// assumes there are no colons in file name!
        startpos = line.indexOf(&quot;:&quot;, fpos);
        if (startpos == -1) {
            return 1;
	// in caller, lineNumber is converted to lineNumber - 1,
	//    this causes an exception if this is 0
        }
        numBuf = new StringBuffer();
        for (int i = startpos+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                numBuf.append(ch);
            } else {
                break;
            }
        }
        lineNumber = Integer.parseInt(numBuf.toString());
        return lineNumber;
    }
    
    private int parseColumnNumber(String line) {
        int fpos;
        int startpos;
        int colNumber;
        Character ch;
        StringBuffer numBuf;
        int colstart = -1;
        
        fpos = line.indexOf(this.fileName);
		// assumes there are no colons in file name!
        startpos = line.indexOf(&quot;:&quot;, fpos); 
        if (startpos == -1) {
            return 0;
        }
        for (int i = startpos+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                // skip line number
            } else {
                colstart = i;
                break;
            }
        }
        if ((colstart == -1) || (line.charAt(colstart) != &#039;:&#039;)) {
            return 0;
        }
        numBuf = new StringBuffer();
        for (int i = colstart+1; i &amp;lt; line.length(); i++) {
            ch = line.charAt(i);
            if (Character.isDigit(ch)) {
                numBuf.append(ch);
            } else {
                break;
            }
        }
        colNumber = Integer.parseInt(numBuf.toString());
        return colNumber;
    }
}
&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;As you can see, we added an OutputListener that does the work of popping us into the editor at exactly the right place where the error is located. The parsing of the error / warning lines to get the line number and column number is ugly, but that&#039;s because &lt;strong&gt;A)&lt;/strong&gt; I didn&#039;t want to have to relearn regular expression syntax for the umpteenth time, and &lt;strong&gt;B)&lt;/strong&gt; I didn&#039;t have 244 Swiss Francs for the ISO Prolog error message standard so I was winging it from the SWI Prolog output. Actually, there are &lt;em&gt;two&lt;/em&gt; ISO Prolog standards documents, so it would have been 488CHF. As &lt;em&gt;if&lt;/em&gt;.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;I suppose I should also mention the StatusDisplayer line. This is one of those things that I couldn&#039;t resist putting in but that gets obnoxious very quickly. When you go to an error line, it displays &quot;Fix me!&quot; on the status line at the bottom of the IDE. Hah hah. So take it out, you don&#039;t like it.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Testing The Final Version&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;Okay, let&#039;s give &#039;er a spin. Clean and build your project then install it to the target IDE as before. Open up the BraveNewWorld project. Wait. Open up sieve.pro. Unfix the error and the warning if you fixed them last time so we have something to work with. Click our &quot;Compile Prolog&quot; button on the toolbar.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss6-4a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:82 --&gt;&lt;img width=&quot;90&quot; height=&quot;68&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss6-4a.serendipityThumb.png&quot; alt=&quot;&quot;  /&gt;&lt;/a&gt;&lt;br /&gt;

We have hyperlinks! Click on an unlinked (white) line in the Prolog output tab to make that window current. Click on one hyperlink, then the other. Notice how the cursor is moved to the editor window to the line and column where the error occurred. Now leave sieve.pro open and open up fib1.pro. Introduce an error into the code, save it, and compile it with our shiny new button. The error hyperlink from that compile should take you to the error in fib1.pro. Now scroll up the Prolog output window to our first compile and click one of the original hyperlinks. Notice that &lt;em&gt;sieve.pro is reselected&lt;/em&gt; and the error position is displayed again. Go ahead, say it, you know you want to: &quot;Gee whiz!&quot;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;So now we can compile our little Prolog hearts out in the NetBeans IDE. We still need to open SWI Prolog to run the stuff, but that&#039;s not so bad. It &lt;em&gt;should&lt;/em&gt; be possible to connect up a Reader in the same way we did with the OutputWriter to allow the interaction, however. Hmmm.... You&#039;re welcome to do that if you want. I haven&#039;t yet, but I&#039;m sure it&#039;s only a matter of time before I have to try it. If you do, let me know how it comes out.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;We now have a pretty decent Prolog IDE embedded within the NetBeans architecture. What&#039;s next? We&#039;re going to create a Prolog project template so we don&#039;t have to stick our lovely, elegant and erudite nonprocedural Prolog source code into an icky stinky Java class library, that&#039;s what&#039;s next. Stay tuned.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Files From This Entry&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partfive.tar.gz&#039;&gt;geewhiz_partfive.tar.gz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a onclick=&quot;javascript:urchinTracker(&#039;/download/uploads/geewhiz/geewhiz_partfive.zip&#039;);&quot; href=&#039;http://hulles.supersized.org/uploads/geewhiz/geewhiz_partfive.zip&#039;&gt;geewhiz_partfive.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;br /&gt;

 
    </content:encoded>

    <pubDate>Wed, 21 May 2008 20:46:21 +0200</pubDate>
    <guid isPermaLink="false">http://hulles.supersized.org/archives/7-guid.html</guid>
    
</item>
<item>
    <title>GeeWhiz Prolog - Part Four - A Visual Prolog Modeler</title>
    <link>http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html</link>
            <category>NetBeans</category>
    
    <comments>http://hulles.supersized.org/archives/6-GeeWhiz-Prolog-Part-Four-A-Visual-Prolog-Modeler.html#comments</comments>
    <wfw:comment>http://hulles.supersized.org/wfwcomment.php?cid=6</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://hulles.supersized.org/rss.php?version=2.0&amp;type=comments&amp;cid=6</wfw:commentRss>
    

    <author>nospam@example.com (Hulles)</author>
    <content:encoded>
    &lt;em&gt;This is Part Four, the fifth part of a series of entries describing an implementation of the Prolog language in the NetBeans IDE. 
&lt;br/&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/2-GeeWhiz-Prolog-Part-Zero-About-the-Project.html&quot; alt=&quot;About the Project&quot;&gt;Part Zero is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/3-GeeWhiz-Prolog-Part-One-Before-We-Start.html&quot; alt=&quot;Before We Start&quot;&gt;Part One is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/4-GeeWhiz-Prolog-Part-Two-Creating-A-File-Type.html&quot; alt=&quot;Creating A File Type&quot;&gt;Part Two is here.&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://hulles.supersized.org/archives/5-GeeWhiz-Prolog-Part-Three-Adding-Language-Support.html&quot; alt=&quot;Adding Language Support&quot;&gt;Part Three is here.&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;&lt;h3&gt;What We&#039;ll Be Doing&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;So far we&#039;ve created an editor for Prolog source code within the NetBeans IDE that supports navigation and syntax highlighting. Most of the previous stuff we&#039;ve done can be found in other tutorials, but now we&#039;re going to branch out from there and explore some unknown territory. Specifically, we&#039;re going to build a visual predicate mapper for Prolog that will look like this when it&#039;s done:&lt;/p&gt;

&lt;br /&gt;&lt;!-- s9ymdb:55 --&gt;&lt;img width=&quot;624&quot; height=&quot;437&quot; style=&quot;border: 0px; padding-left: 5px; padding-right: 5px;&quot; src=&quot;http://hulles.supersized.org/uploads/geewhiz/ss4-big.png&quot; alt=&quot;&quot;  /&gt;&lt;br /&gt;

&lt;p&gt;Frankly, I&#039;m not sure how useful the mapper really is in actual Prolog programming, but so far I have used it to find missing references in Prolog code I wrote and to get an overview of code others have written. For these use cases the diagram thing really does come in handy.&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;My starting point for this segment of the project was the excellent tutorial, &lt;a onclick=&quot;javascript:urchinTracker(&#039;/extlink/wiki.netbeans.org/VisualDatabaseExplorer&#039;);&quot; href=&quot;http://wiki.netbeans.org/VisualDatabaseExplorer&quot; title=&quot;NetBeans link&quot;&gt;&quot;A Visual Database Explorer for NetBeans&quot;&lt;/a&gt;. Thanks to Toni Epple for providing a lot of useful information. I should also confess here that I&#039;m far from an expert in the NetBeans Visual Library, but learning more about it is high on my to-do list. The library so far seems easy to use, featureful and well worth investigating further.&lt;/p&gt;
&lt;br /&gt;&lt;h3&gt;Creating A First-Cut Diagram&lt;/h3&gt;&lt;br /&gt;
&lt;p&gt;The first thing we&#039;ll do is create a static sample diagram in GeeWhiz using techniques described in the Visual Database Explorer tutorial, so let&#039;s create a new action in the project. This action will add an item to the main menu that opens our diagram window. Right-click on GeeWhiz in the Projects tab and select &quot;New&quot; &quot;Action&quot;.

&lt;br /&gt;&lt;a class=&#039;serendipity_image_link&#039; href=&#039;http://hulles.supersized.org/uploads/geewhiz/ss5-1a.png&#039; target=&quot;_blank&quot;&gt;&lt;!-- s9ymdb:56 --&gt;&lt;img width=&quot;90&quot; height=&quot;63&quot; style=&quot;border: 0px; padding