wiki1162: CustomControls

Creating Custom Controls#

All Controls must implement the Control interface, which has two methods: getUi() and registered(DataCoreProvider). When the Control is placed on the canvas, it is registered with the parent container (normally the canvas itself - a DataAnchorPane), which in turn calls registered. The Control then can bind to values it cares about with DataCoreProvider#getObservable(String) or ignore it all together. When the UI is required, getUi is called and the resulting JavaFX Node is added to the JavaFX Scene Graph. NOTE: getUi MUST return the exact same node over the life of the control.

Creating a FXML-based Control#

This is the recommended way to create simple controls. First, find an appropriate base or create a new one in Java. The current bases are found in sfxlib/src/dashfx/controls/bases/  and are:

  • These are abstract and thus can't be used directly from FXML.

Once you have picked a base, create a new file (extension .fxml) with the following contents, and fill in the missing sections as needed:

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<?import dashfx.controls.bases.*?>
<!-- Change imports as needed -->
<?language javascript?> <!-- Optional, only if you need interactivity -->

<YourControlBase fx:id="base" xmlns:fx="http://javafx.com/fxml">
	<fx:script>
		// if you want/need interactivity, add javascript functions
		// to be called here from event handlers
	</fx:script>
	<ui>
		<!-- Standard JavaFX controls. Bind to base.value and similar -->
	</ui>
</YourControlBase>

For inspiration, see the built-in controls that use fxml in sfxlib/src/dashfx/controls/*.fxmlAlso see the JavaFX documentation.

Creating a Java-based control#

If your control is more complex and pushes FXML & Javascript to the limits, you can write it in Java. It is recommended that you attempt to extend a ControlBase or Data class (like DataVBox, DataAnchorPane, etc) if possible to avoid having to manually manage the path. If not, manually impement Control.

See sfxlib/src/dashfx/controls/Scheduler.java or sfxlib/src/dashfx/controls/ArrayLister.java for some examples.

Creating a JRuby-based control#

NOTE: this is not well tested in jars.

Similar to Java-based, but in JRuby. Note that you must define 3 methods: registered(arg), getUi(), and ui() as the calling code depends on the Java interop to translate the last two. Explicitly implmenting is optional for non-parents. see https://bitbucket.org/byteit101/sfx/src/tip/plugins/built-in/tab-switcher/tab_switcher.rb?at=default for the only example

Packaging Custom Controls#

There are two ways to package plugins: in a jar or in a folder. Java code MUST use the Jar option, FXML & JRuby can use either. Plugins hold one or more Controls and other options.

Creating a manifest#

All forms must use a manifest to expose controls. The manifest is YAML and starts as follows:

API: 0.1
Name: Name of your plugin
Description: Description of what your plugin does
# Note the version number is any valid RubyGems version, like 4.5.1b3 for 4.5.1 beta 3
Version: 1.0
Plugin ID: # generate a unique uuid

After that, you can add some controls:

Controls:
-
  Name: Name of FXML Control
  Description: Will be shown as tooltip when you hover over in toolbox
  Source: /your/file.fxml
  Group Type: Subsystem # optional, for composite controls, what is found in ~TYPE~
  Category: Custom # toolbox to add this to
  Save Children: false # optional, for composite controls this should be false
  Sealed: true # optional, for composite controls this should be true
  Placeholders: [command] # FXML placeholders, optional
  Defaults: # optional section
    value: foo # if you want to assign default values
    min: baz # then put them here
    max: bar # see https://bitbucket.org/byteit101/fx-livewindow/src/tip/src/manifest.yml?at=default
-
  Name: Name of JRuby control
  Image: /icon.png # optional toolbox icon
  Source: /example/ruby/file.rb # file to find the class
  Class: Example::Ruby::Control # the ruby class
-
  Class: com.example.java.MyControl # if your java class has annotations, this is all you need
  # you can add the other fields here to override the annotations

If you don't have any java classes, you can put this in a folder inside the plugins folder and SFX should detect it. View loaded plugins in (Wrench icon) > plugins.

See the sfx/plugins/built-in folder for an example of how to structure it.

If you have java controls, make a jar and put it in the plugins folder.