How to use the diff view in my own application/plugin

Apache NetBeans Wiki Index

Note: These pages are being reviewed.

Show non-editable diff for files

@ActionID(category = "Tools", id = "org.my.diff.DiffViewerAction")
@ActionRegistration(asynchronous = true, displayName = "#CTL_DiffViewerAction")
@ActionReference(path = "Menu/Tools", position = 0)
@Messages("CTL_DiffViewerAction=Open Diff Viewer")
public final class DiffViewerAction implements ActionListener {

     @Override
    public void actionPerformed(ActionEvent e) {
        StreamSource local = StreamSource.createSource("name1", "title1", "text/html", new File("C:/tutorials/nbm-google.html"));
        StreamSource remote = StreamSource.createSource("name2","title2", "text/html", new File("C:/tutorials/72/nbm-google.html"));
        diff(local, remote);
    }

    public void diff(final StreamSource local, final StreamSource remote) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    DiffView view = Diff.getDefault().createDiff(local, remote);
                    TopComponent tc = new TopComponent();
                    tc.setDisplayName("Diff Viewer");
                    tc.setLayout(new BorderLayout());
                    tc.add(view.getComponent(), BorderLayout.CENTER);
                    tc.open();
                    tc.requestActive();
                } catch (IOException ex) {
                }
            }
        });
    }

}

or

        String contentType = fo.getMIMEType();
        DiffView view = Diff.getDefault().createDiff(
                StreamSource.createSource("Before", "Before", contentType, new StringReader(beforeText)),
                StreamSource.createSource("After", "After", contentType, new StringReader(afterText))
        );
        Component diffViewComponent = view.getComponent();

See

Show editable diff for nodes with FileObject in node’s lookup

Show editable diff for a FileObject and an arbitrary base source

You have to an editable StreamSource for your FileObject to create a editable diff viewer.

The following sample app will compare the given FileObject (from the Lookup) with its base. The base - in this very simplified example – is a String read from a file.

package de.markiewb.netbeans.sample.editablediff;

//...

@ActionID(category = "Edit", id = "de.markiewb.netbeans.sample.editablediff.EditableDiffAction")
@ActionRegistration(displayName = "#CTL_DiffAction")
@ActionReferences({
    @ActionReference(path = "Editors/Popup")})
@Messages("CTL_DiffAction=Editable diff...")
public final class EditableDiffAction implements ActionListener {

    private final FileObject file;

    public EditableDiffAction(FileObject context) {
	this.file = context;
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
	final String baseText = getOriginalText(file);
	final StreamSource base = StreamSource.createSource("name1", "base", file.getMIMEType(), new StringReader(baseText));
	final StreamSource modified = EditableStreamSource.createEditableSource("name2", "modified", file.getMIMEType(), file);

	openDiffWindow(file, modified, base, "Diff of " + file.getNameExt() + " to original");
    }

    public void openDiffWindow(final FileObject localFile, final StreamSource local, final StreamSource remote, final String title) {
	SwingUtilities.invokeLater(new Runnable() {
	    @Override
	    public void run() {
		try {
		    final TopComponent tc = new TopComponent();
		    tc.setDisplayName(title);
		    tc.setLayout(new BorderLayout());
		    makeDiffWindowSaveable(tc, localFile);
		    tc.add(DiffController.createEnhanced(remote, local).getJComponent(), BorderLayout.CENTER);
		    tc.open();
		    tc.requestActive();
		} catch (IOException ex) {
		}
	    }
	});
    }

    /**
     * Put the node of dataObject of the fileObject into "globallookup". This
     * allows saving via CTRL-S shortkey from within the editable diff TC. See
     * https://bz.apache.org/netbeans/show_bug.cgi?id=223703
     *
     * @param tc
     * @param fileObject
     */
    private void makeDiffWindowSaveable(TopComponent tc, FileObject fileObject) {
	if (tc != null) {
	    Node node;
	    try {
		node = DataObject.find(fileObject).getNodeDelegate();
	    } catch (DataObjectNotFoundException e) {
		node = new AbstractNode(Children.LEAF, Lookups.singleton(fileObject));
	    }
	    tc.setActivatedNodes(new Node[]{node});
	}
    }

    public String getOriginalText(FileObject file) {
	// TODO this is only a mockup
	// TODO get original text from other sources like SCM, DB, template files..
	try {
	    return file.asText("UTF-8").replace("public ", "public final ");
	} catch (IOException ex) {
	    Exceptions.printStackTrace(ex);
	}
	return "";
    }

    public static class EditableStreamSource extends StreamSource {

	private String name, title, mimeType;
	private FileObject fileObject;

	private EditableStreamSource(String name, String title, String mimeType, FileObject fileObject) {
	    this.name = name;
	    this.title = title;
	    this.mimeType = mimeType;
	    this.fileObject = fileObject;
	}

	public static StreamSource createEditableSource(String name, String title, String mimeType, FileObject fileObject) {
	    return new EditableStreamSource(name, title, mimeType, fileObject);
	}

	@Override
	public String getName() {
	    return this.name;
	}

	@Override
	public String getTitle() {
	    return this.title;
	}

	@Override
	public Lookup getLookup() {
	    return Lookups.fixed(fileObject);
	}

	@Override
	public boolean isEditable() {
	    return fileObject.canWrite();
	}

	@Override
	public String getMIMEType() {
	    return mimeType;
	}

	@Override
	public Reader createReader() throws IOException {
	    return new FileReader(FileUtil.toFile(fileObject));
	}

	@Override
	public Writer createWriter(Difference[] conflicts) throws IOException {
	    return null;
	}
    }
}

PS: There is a small trick to enable the "save"-action (Menubar File→Save / CTRL-S) for your new editable diff, which won’t get enabled after changing content in the right editor pane of the diff viewer by default. You have to associate your node to the TopComponent – see makeDiffWindowSaveable(). Thanks to Ondrej Vrabec for the solution – see https://bz.apache.org/netbeans/show_bug.cgi?id=223703.