The SDK contains a Visual Studio macro simplifying development of document nodes. It injects boiler plate code based on the private fields defining a custom Spotfire document node.
Overview
Macros is a powerful Visual Studio feature. It enables
automation of repetitive tasks, enabling the macro end user
to quickly and accurately perform otherwise error prone actions,
like creating document nodes in Spotfire.
The SpotfireSDKMacros.vsmacros macro project is
available in the VisualStudioMacros folder of the
SDK as of version 2.2.
Installing the Spotfire SDK Macros
In Visual Studio, open the Macro Explorer (Alt
+ F8). Right-click the Macros icon and select
Load Macro Project... Browse to SDK\VisualStudioMacros,
select the SpotfireSDKMacros.vsmacros file
and click OK.
The Document Model Module
The InsertTemplatecodeBasedOnPrivateFields
macro of the DocumentModel macro module is
the only module recommended for use. It is convenient when creating
document nodes. Since document nodes add complexity and at times
may impede performance, even if carefully designed, first consider
if you really need a document node. If you do, remember that
the macro does not provide design, but simply adds boiler plate
code based on private fields.
|
|
Using the Macro
Suppose you need a document node representing a coordinate. First
create a class inheriting from
DocumentNode
and declare the following fields:
[Serializable]
[PersistenceVersion(1, 0)]
internal partial class MyCoordinate : DocumentNode
{
#region Private Fields
private readonly string title;
private readonly UndoableProperty<int> width;
private readonly UndoableProperty<int> height;
private readonly RuntimeProperty<int> diagonal;
#endregion // Private Fields
#region Code generated by the macro InsertTemplatecodeBasedOnPrivateFields
// Place cursor on the line below this line and run the "InsertTemplatecodeBasedOnPrivateFields" macro
#endregion // Code generated by the macro InsertTemplatecodeBasedOnPrivateFields
}
To create the code implementing the document node based on these
fields, place the cursor in the position indicated above and
run the InsertTemplatecodeBasedOnPrivateFields
macro from the Macro Explorer. Result:
[Serializable]
[PersistenceVersion(1, 0)]
internal partial class MyCoordinate : DocumentNode
{
#region Private Fields
private readonly string title;
private readonly UndoableProperty<int> width;
private readonly UndoableProperty<int> height;
private readonly RuntimeProperty<int> diagonal;
#endregion // Private Fields
#region Code generated by the macro InsertTemplatecodeBasedOnPrivateFields
// Place cursor on the line below this line and run the "InsertTemplatecodeBasedOnPrivateFields" macro
#region Classes for property names
/// <summary>
/// Contains property name constants for the public properties of <see cref="MyCoordinate"/>.
/// </summary>
public new abstract class PropertyNames : DocumentNode.PropertyNames
{
/// <summary>
/// The name of the property Width.
/// </summary>
public static readonly PropertyName Width = CreatePropertyName("Width");
/// <summary>
/// The name of the property Height.
/// </summary>
public static readonly PropertyName Height = CreatePropertyName("Height");
/// <summary>
/// The name of the property Diagonal.
/// </summary>
public static readonly PropertyName Diagonal = CreatePropertyName("Diagonal");
}
private abstract class PrivatePropertyNames : DocumentNode.PropertyNames
{
/// <summary>
/// The name of the property Title.
/// </summary>
public static readonly PropertyName Title = CreatePropertyName("Title");
}
#endregion // Classes for property names
#region Public properties
/// <summary>
/// Gets or sets Width.
/// </summary>
public int Width
{
get { return this.width.Value; }
set { this.width.Value = value; }
}
/// <summary>
/// Gets or sets Height.
/// </summary>
public int Height
{
get { return this.height.Value; }
set { this.height.Value = value; }
}
/// <summary>
/// Gets Diagonal.
/// </summary>
public int Diagonal
{
get { return this.diagonal.Value; }
}
/// <summary>
/// Gets Title.
/// </summary>
public string Title
{
get { return this.title; }
}
#endregion // Public properties
#region Construction
/// <summary>
/// Initializes a new instance of the <see cref="T:MyCoordinate"/> class./// </summary>
public MyCoordinate()
{
CreateProperty(PropertyNames.Width, out this.width, default(int));
CreateProperty(PropertyNames.Height, out this.height, default(int));
CreateReadOnlyProperty(PrivatePropertyNames.Title, default(string), out this.title);
InitRuntimeProperties(out this.diagonal);
}
#endregion // Construction
#region Runtime properties
private void InitRuntimeProperties(out RuntimeProperty<int> diagonal)
{
CreateRuntimeProperty<int>(PropertyNames.Diagonal,
out diagonal,
DiagonalTrigger,
DiagonalCompute);
}
private static readonly StatelessDependencyDeclarer DiagonalTrigger = DiagonalDependencyDeclarer;
private static Trigger DiagonalDependencyDeclarer(DocumentNode node)
{
MyCoordinate thisNode = (MyCoordinate)node;
// TODO: Insert the trigger declaration for the Diagonal property here.
throw new NotImplementedException();
}
private static readonly StatelessPropertyComputer<int> DiagonalCompute = DiagonalPropertyComputer;
private static int DiagonalPropertyComputer(DocumentNode node)
{
MyCoordinate thisNode = (MyCoordinate)node;
// TODO: Insert the computation code for the Diagonal property here.
throw new NotImplementedException();
}
#endregion // Runtime properties
#region ISerializable Members
/// <summary>Implements ISerializable.</summary>
protected MyCoordinate(SerializationInfo info, StreamingContext context)
: base(info, context)
{
DeserializeReadOnlyProperty(info, context, PrivatePropertyNames.Title, out this.title);
DeserializeProperty<Int32>(info, context, PropertyNames.Width, out this.width);
DeserializeProperty<Int32>(info, context, PropertyNames.Height, out this.height);
InitRuntimeProperties(out this.diagonal);
}
/// <summary>Implements ISerializable.</summary>
protected override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
SerializeReadOnlyProperty(info, context, PrivatePropertyNames.Title, this.title);
SerializeProperty<Int32>(info, context, this.width);
SerializeProperty<Int32>(info, context, this.height);
}
#endregion // ISerializable Members
#endregion // Code generated by the macro InsertTemplatecodeBasedOnPrivateFields
}