Developing a Vectorworks 2011 tool plug-in, TDD-style – Episode 1

In Episode 0, we set the goal for this series: To develop a Vectorworks plug-in tool which creates a green line if both clicks are on the same Vectorworks polygon and creates a red line if the clicks are on two different polygons.

We will be using a slightly modified version of CppUnitLite2, for more details on how the testing targets are integrated in the Xcode projects please refer to Episode 0 of the plug-in object series.

As in our plug-in object series, the first challenge is “How do we start”?

As our tool will require two clicks, we may get away with subclassing VWToolDefaultLine_EventSink to implement the interactive behavior of the tool. Of course, we won’t be able to use a VWToolDefaultLine_EventSink in our testing target, as the testing environment runs as a separate application. So we need to come up with our own “Vectorworks tool” class. Let’s do that and see were it leads us.

What to test first? Our tool will be collecting up to two clicks (“tool points” in Vectorworks SDK lingo). Upon initialization, there are no tool point in the collection:

#include "CppUnitLite2.h"

TEST_N(ToolObjectShouldHaveNoPointsUponInitialization)
{
	MockRedGreenLineTool vwTool;

	CHECK_EQUAL(0, vwTool.GetNumToolPoints());
}

Not an awful lot of sophistication here, but we sure know how to make this test pass (doing the simplest thing that could possibly work):

class MockRedGreenLineTool {
	
public:
	
	short GetNumToolPoints() const {
		return 0;
	}
	
};

Compiles, links and even passes the test. Excellent. We’re off to a great start. Now for some more, ahm, sophistication. The tool should store the tool points (to create the line later on – we have no clue yet how to do that in a test-first fashion, but let’s just follow our chosen path of rather trivial steps for a while):

#include "CppUnitLite2.h"

TEST_N(ToolObjectShouldRememberToolPoints)
{
	MockRedGreenLineTool vwTool;
	
	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));
	
	CHECK_EQUAL(2, vwTool.GetNumToolPoints());
}

Making this test pass is no challenge either (even for a small mind like me):

class MockRedGreenLineTool {
	
public:
	
 	void AddPoint(const WorldPt3& p) {
		fToolPoints.PushData(p);
	}	

	short GetNumToolPoints() const {
		return fToolPoints.NumItems();
	}
	
	TSmallArray<WorldPt3> fToolPoints;

};

Now that we’re on a roll, let’s add one more “event” to our class, removing tool points. Users will be able to back out of a Vectorworks tool step by step by removing the last tool point added.

TEST_N(ToolObjectPoppingToolPoints)
{
	MockRedGreenLineTool vwTool;
	
	vwTool.AddPoint(WorldPt3(0, 0, 0));
	vwTool.AddPoint(WorldPt3(50, 0, 0));
	
	CHECK_EQUAL(2, vwTool.GetNumToolPoints());

	vwTool.PopPoint();

	CHECK_EQUAL(1, vwTool.GetNumToolPoints());

	vwTool.PopPoint();

	CHECK_EQUAL(0, vwTool.GetNumToolPoints());
}

Luckily, TSmallArray features a method to remove the last entry added, so making the test pass is straightforward:

class MockRedGreenLineTool {
	
public:

	virtual void PopPoint() {
		fToolPoints.PopData();
	}

	// ...
	
};	

Where are we at? We now have a tool class collecting tool points (with the added bonus of being able to remove those tool points later). There are three questions which come to our mind:

  • We need to somehow connect MockRedGreenLineTool to the VWToolDefaultLine_EventSink
  • MockRedGreenLineTool needs to be able to know about the clicks being on a polygon
  • MockRedGreenLineTool needs to create a “red or green line object”

Let’s try to tackle connecting MockRedGreenLineTool to VWToolDefaultLine_EventSink in the next episode.

Previous Episode | Next Episode