Templating and Copying Visual Elements

Field encourages you to use visual elements for anything and everything — for example the TopologyPlugin (one of the tools on the mouse tools palette) even uses them for the edges between nodes; since one often constructs "visualizations" of data over time that you end up wanting to edit and clean, these visualizations should be made out of visual elements. Clearly, in order for this to happen, making, editing and deleting visual elements needs to be easy. This pages collects the range of ways of doing this.

First of all, let's just mention that you can copy elements with the mouse by holding command and shift, and dragging the elements that you'd like to copy. However, there are some times when you'd like to make, edit and copy elements using code.

Creating boxes with code

Here's the super-flexible way of creating many elements is with the code like:

otherElement, component, overrides 
    = VisualElement.createWithName(Rect(40,40,100,100), _self.root,  
        VisualElement, DraggableComponent, DefaultOverride, "banana")

This creates a default looking visual element (the usual grey box) at (40,40) with dimensions (100,100) which dispatches to the root of the sheet (see SelfAndProperties).

The last three parameters are the classes that will supply the iVisualElement, iComponent and iVisualElementOverrides implementations.

  • For iVisualElement you are pretty much limited to VisualElement the base class for all boxes.
  • For iComponent you have the choice between DraggableComponent, PlainDraggableComponent and PlainComponent.
  • and for iVisualElementOverrides I recommend starting with DefaultOverrides (or perhaps SplineComputingOverrides and 'upgrading' it later using Mixins)

You are also free to have the newly created element dispatch to something other than _self.root_self is often useful — but remember, this newly created component will have all of its missing properties filled in by the parent it dispatches to, including the python_source_v !

But otherElement is now the box created, and it acts just like _self, you can set properties on it

otherElement.python_source_v = """
print "hello world !"
"""

otherElement() # prints "hello world !"

Finally, you can delete an element by calling VisualElement.delete(_self.root, otherElement).

Copying other elements

The code above looks a little long, but the reason that it hasn't been packaged up into something more common is that it isn't actually used that much. Far more common than creating an element from scratch are the other techniques outlined below.

The first is copying elements from the sheet, using the Templating utility class.

newElement = Templating.simpleCopy(someElement, _self.root)
newElement.setFrame(Rect(50,50,100,100))

This makes a new element, that dispatches to the root, that copies all of the properties that are locally stored in someElement. Again, you can then set properties on what is returned. Two things make this better than creating it from scratch. Firstly you get to use the editor etc. to author the template element in the first place (which is certainly better than writing long python """ strings).

Templating from other sheets

You can also copy material from other Field sheets without loading them. If you right-click on a visual element and select "mark as template" you are invited to give this visual element a new "template name". Nothing else happens to this element, it's just marked as having this additional name. Once the sheet is saved, you can then find these elements from the "Element File System Browser" (from the File menu) in the templates folder.

From the browser, you can insert this element into a new sheet. In fact you can insert any element from any sheet into a currently open sheet. Just drag it over from the File System view. Digging down and dragging individual properties to boxes will copy just those properites over. Dragging an entire sheet will insert everything.

"Templates" are just easier to find and can be groups of boxes: template names automatically hierarchicalize using periods — just like, say, java packages. So some.template.this.is is a template called is in the folder this in the folder template in the folder some in the templates "folder". Inside code its a matter of:

inserted = Templating.elementFromKnownTemplate(name, _self.root)

You can also copy the entire sheet into the open sheet using the element file system browser, or from code:

insertedElements = Templating.elementsFromKnownSheet(name)