Chapter 10. Concepts for use in specialized plugins

Table of Contents

Plugins than produce a plot
Drawing a plot to the output window
Adding preview functionality
Generic plot options
A canonical example
Context-dependent plugins
X11 device context
Import data context
Referencing the current object
Repeating (a set of) options
"Driven" optionsets
Alternatives: When not to use optionsets

This chapter contains information on some topics that are useful only to certain classes of plugins.

Plugins than produce a plot

Creating a plot from a plugin is easy to do. However, there are a few sublte gotchas to avoid, and also some great generic functionality that you should be aware of. This section shows you the basic concepts, and concludes with a canonical example that you should follow whenever creating plot plugins.

Drawing a plot to the output window

In order to draw a plot to the output window, use rk.graph.on() directly before creating the plot, and rk.graph.off(), directly afterwards. This is similar to e.g. callling postscript() and dev.off() in a regular R session.

Importantly, however, you must always call rk.graph.off() after calling rk.graph.on(). Otherwise the output file will be left in a broken state. To ensure rk.graph.off() really gets called, you should wrap all R commands between the two calls in try() statement. Never heard of that? Don't worry, it's easy. All you need to do is follow the pattern shown in example, below.

Adding preview functionality

A very useful feature for all plugins generating a plot/graph is to provide an automatically updating preview. To do so, you will need two things: Adding a <preview> checkbox to your GUI definition, and adjusting the generated code for the preview.

Adding a <preview> checkbox is simple. Just place the following somewhere in your GUI. It will take care of all the behind-the-scenes magic of creating a preview device, updaing the preview whenever the setting have changed, etc. Example:

	<document>
		[...]
		<dialog [...]>
			[...]
			<preview id="preview"/>
			[...]
		</dialog>
		[...]
	</document>
		

And that's it for the GUI definition.

Adjusting the JS template is a little more work. You will have to create a new function called preview() in addition to the preprocess(), calculate(), etc. functions. This function should generate the code needed to produce the plot, and only that. Esp. no printing of headers, rk.graphics.on(), or similar calls. See the example, below for the typical pattern that you will use.

Generic plot options

You will have noticed that most plotting plugins in RKWard provide a wide range of generic options e.g. for customizing axis titles or figure margins. Adding these options to your plugin is easy. They are provided by an embeddable plugin called rkward::plot_options. Embed this in your plugin UI like this:

	<document>
		[...]
		<logic [...]>
			<connect client="plotoptions.xvar" governor="x.available"/>
			<set id="plotoptions.allow_type" to="true"/>
			<set id="plotoptions.allow_ylim" to="true"/>
			<set id="plotoptions.allow_xlim" to="false"/>
			<set id="plotoptions.allow_log" to="false"/>
			<set id="plotoptions.allow_grid" to="true"/>
		</logic>
		<dialog [...]>
			[...]
			<embed id="plotoptions" component="rkward::plot_options" as_button="true" label="Plot Options"/>
			[...]
		</dialog>
		[...]
	</document>
		

This will add a button to your UI to bring up a window with plot options. The logic section is just an example. It allows you some control over the plot options plugin. Read more in the plot_options plugin's help page (linked from the help page of any plugin providing the generic options).

Next you need to make sure that the code corresponding to your plot options is added to the generated code for your plot. To do so, fetch the properties code.preprocess, code.printout, and code.calculate from the embedded plot options plugin, and insert them into your code as shown in the example, below.

A canonical example

Here's an example .JS file that you should use as a template, whenever you create a plotting plugin:

	function preprocess () {
		// the "somepackage" is needed to create the plot
		ecoh ("require (somepackage)\n");
	}

	function printout () {
		// all the real work is moved to a custom defined function doPrintout (), below

		doPrintout (true);	// in this case, 'true' means: We want all the headers that should be printed in the output, not just the preview
	}

	function preview () {
		// we call all stages of the general code. Only the printout () function needs to be slightly different for the plot preview
		preprocess ();
		// calculate (); // in this example, the plugin has no calculate () function.
		doPrintout (false);	// in this case, 'false' means: Create the plot, but not any headers or other output.
	}

	function doPrintout (full) {
		// this function takes care of generating the code for the printout() section. If "full" is set to true,
		// it generates the full code, including headers. If full is set to false, only the essentials will
		// be generated.

		if (full) {
			echo ('rk.header ("An example plot")\n\n');
			echo ('rk.graph.on ()\n');
		}
		// only the following section will be generated for full==false

		// remember: everything between rk.graph.on() and rk.graph.off() should be wrapped inside a try() statement:
		echo ('try ({\n');
		// insert any option-setting code that should be run before the actual plotting commands.
		// The code itself is provided by the embedded plot options plugin. printIndentedUnlessEmpty() takes care of pretty formatting.
		printIndentedUnlessEmpty ('\t', getString ("plotoptions.code.preprocess"), '', '\n');

		// create the actual plot. plotoptions.code.printout provides the part of the generic plot options
		// that have to be added to the plotting call, itself.
		echo ('plot (5, 5' + getString ("plotoptions.code.printout") + ')\n');

		// insert any option-setting code that should be run after the actual plot.
		printIndentedUnlessEmpty ('\t', getString ("plotoptions.code.calculate"), '\n');
		echo ('})'\n);	// the closure of the try() statement

		if (full) {
			echo ('rk.graph.off ()\n');
		}
	}