How to Make My Custom Style Serializable

Tips & Tricks

Summary

If your application uses custom item styles, you might want to serialize them to GraphML. This approach also applies to other classes which are serialized.

This article was written for an older version. It is only online as a reference for customers using this old version. The information it contains is probably out of date.

The latest information can be found in the yFiles documentation

Description

Making the Style Serializable

If your style contains a parameterless constructor and all properties have a public getter and setter, your style is already serializable. If not, you can write a MarkupExtension. The MarkupExtension should have all the necessary public properties that are needed to create the style instance.

Your style could look like this:

yfiles.module("my.module", function(exports) {
  exports.MyNodeStyle = new yfiles.ClassDefinition(function() {
    return {
      '$extends': yfiles.drawing.SimpleAbstractNodeStyle,

      'constructor': function(color, cornerRounding) {
        yfiles.drawing.SimpleAbstractNodeStyle.call(this, yfiles.drawing.DefaultVisual.$class);
        this.color = color;
        this.cornerRounding = cornerRounding;
      },

      'createVisual': function(node, context) { /*...*/ }
    };
  })
});

This style is not serializable by default, since it does not have a parameterless constructor and the color and cornerRounding are not publicly accessible. Create a MarkupExtension for the style.

yfiles.module("my.module", function(exports) {
  exports.MyNodeStyleExtension = new yfiles.ClassDefinition(function() {
    return {
      '$extends': yfiles.system.MarkupExtension,

      'colorField': null,
      'cornerRoundingField': null,

      'color': {
        'get': function() { return this.colorField; }
        'set': function(value) { this.colorField = value; }
      },

      'cornerRounding': {
        'get': function() { return this.cornerRoundingField; }
        'set': function(value) { this.cornerRoundingField = value; }
      },

      'provideValue ': function(serviceProvider) {
        return new my.module.MyNodeStyle(this.color, this.cornerRounding);
      }
    };
  })
});

Now register a serialization handler that calls the MarkupExtension for instances of MyNodeStyle.

var graphMLIOHandler = graphControl.getGraphMLIOHandler();
graphMLIOHandler.addHandleSerializationListener(function(s, arg){
  if (arg.item instanceof my.module.MyNodeStyle){
    arg.replaceItem(arg.item.createMarkupExtension(), yfiles.system.MarkupExtension.$class);
    arg.handled = true;
  }
})

Also add the createMarkupExtension method to the style implementation.

yfiles.module("my.module", function(exports) {
  exports.MyNodeStyle = new yfiles.ClassDefinition(function() {
    return {
      '$extends': yfiles.drawing.SimpleAbstractNodeStyle,

      'constructor': function(color, cornerRounding) {
        yfiles.drawing.SimpleAbstractNodeStyle.call(this, yfiles.drawing.DefaultVisual.$class);
        this.color = color;
        this.cornerRounding = cornerRounding;
      },

      'createVisual': function(node, context) { /*...*/ },

      'createMarkupExtension': function() {
        var extension = new my.module.MyNodeStyleExtension();
        extension.color = this.color;
        extension.cornerRounding = this.cornerRounding;
        return extension;
      }
    };
  })
});

Adding a Namespace Definition

Use the XmlnsDefinitionAttribute and XmlnsPrefixAttribute to add symbolic names for your module names.

yfiles.module("my.module", function (exports) {
    exports.$meta = function () {
      return [
        yfiles.system.XmlnsDefinitionAttribute("http://www.my.url/my/application", "my.module"),
        yfiles.system.XmlnsPrefixAttribute("http://www.my.url/my/application", "myName")];
    };
    // ...
  });

This will result in nice output in the GraphML file.

<myName:MyNodeStyle xmlns:myName="http://www.my.url/my/application"/>

Categories this article belongs to:
yFiles for HTML > Other
Applies to:
yFiles for HTML: 1.3, 1.4
Keywords:
Style - INodeStyle - IEdgeStyle - ILabelStyle - Namespace - Serialization - GraphML - MarkupExtension