Custom LiveWindow widget not appearing on SmartDashboard

I’m trying to turn a class which controls the wheels along a single side of the robot into a custom LiveWindow. It works fine normally, but it doesn’t appear to be appearing on the SmartDashboard during Test mode. The individual speed controllers that the class is using are labeled as “ungrouped” inside the SmartDashboard window.

I tried following the recommendation here: http://www.chiefdelphi.com/forums/showthread.php?p=1233952 and set the SmartDashboardType to be “Speed Controller”, but that didn’t appear to work.

Could somebody help me identify what I’m doing wrong?

My header file:

#ifndef DRIVE_COMPONENTS_H
#define DRIVE_COMPONENTS_H

#include "WPILib.h"
#include "../../Misc/Tools.h"

static const std::string kSpeedLabel = std::string("Speed");
static const std::string kDirectionLabel = std::string("Direction Multiplier (1 or -1)");

class Tread : public PIDOutput, public LiveWindowSendable, public ITableListener {
public:
	/**
	 * \brief Specifies the direction the motors should spin to move forwards
	 */
	enum Direction {
		kForward = 1,
		kReverse = -1
	};
	Tread(SpeedController *motor);
	Tread(SpeedController *front, SpeedController *back);
	Tread(std::vector<SpeedController*> motors);
	virtual ~Tread();
	
	void SetSpeed(double speed);
	Direction GetDirection();
	void SetDirection(Direction direction);
	double GetSpeed();
	
	// Required by PIDOutput
	void PIDWrite(float output);
	
	// Required by Sendable, which LiveWindowSendable inherits from.
	void InitTable(ITable *subtable);
	ITable* GetTable();
	std::string GetSmartDashboardType();
	
	// Required by LiveWindowSendable
	void UpdateTable();
	void StartLiveWindowMode();
	void StopLiveWindowMode();
	
	// Required by ITableListener
	void ValueChanged(
			ITable *source, 
			const std::string &key, 
			EntryValue value, 
			bool isNew);
private:
	ITable *m_table;
	double m_speed;
	Direction m_direction;
	std::vector<SpeedController*> m_motors;
};

#endif

My C++ file:


#include "DriveComponents.h"


Tread::Tread(SpeedController *motor) :
		PIDOutput(),
		LiveWindowSendable(),
		ITableListener(),
		m_speed(0),
		m_direction(kForward) {
	m_motors.push_back(motor);
	m_table = NULL;
}
	
Tread::Tread(SpeedController *front, SpeedController *back) :
		PIDOutput(),
		LiveWindowSendable(),
		ITableListener(),
		m_speed(0),
		m_direction(kForward) {
	m_motors.push_back(front);
	m_motors.push_back(back);
	m_table = NULL;
}

Tread::Tread(std::vector<SpeedController*> motors) :
		PIDOutput(),
		LiveWindowSendable(),
		ITableListener(),
		m_speed(0),
		m_direction(kForward) {
	m_motors = motors;
	m_table = NULL;
}

Tread::~Tread() {
	// empty
}

void Tread::SetSpeed(double speed) {
	SmartDashboard::PutNumber("Tread", speed);
	m_speed = Tools::Limit(speed, -1.0, 1.0);
	std::vector<SpeedController*>::iterator it;
	for (it = m_motors.begin(); it != m_motors.end(); ++it) {
		(*it)->Set(m_speed * m_direction);
	}
}

Tread::Direction Tread::GetDirection() {
	return m_direction;
}

void Tread::SetDirection(Tread::Direction direction) {
	m_direction = direction;
}
	
double Tread::GetSpeed() {
	return m_speed;
}

void Tread::PIDWrite(float output) {
	m_speed = Tools::Limit(output, -1.0, 1.0);
	std::vector<SpeedController*>::iterator it;
	for (it = m_motors.begin(); it != m_motors.end(); ++it) {
		(*it)->PIDWrite(m_speed * m_direction);
	}
}

void Tread::InitTable(ITable *subtable) {
	if (m_table != NULL) {
		// Replace the existing table
		m_table->RemoveTableListener(this);
	}
	m_table = subtable;
	UpdateTable();
}

ITable* Tread::GetTable() {
	return m_table;
}

std::string Tread::GetSmartDashboardType() {
	return "Speed Controller";
}

void Tread::UpdateTable() {
	if (m_table != NULL) {
		m_table->PutNumber(kSpeedLabel, GetSpeed());
		m_table->PutNumber(kDirectionLabel, GetDirection());
	}
}

void Tread::StartLiveWindowMode() {
	SetSpeed(0);
	m_table->AddTableListener(this, true);
}

void Tread::StopLiveWindowMode() {
	SetSpeed(0);
	m_table->RemoveTableListener(this);
}

void Tread::ValueChanged(
		ITable *source, 
		const std::string &key, 
		EntryValue value, 
		bool isNew) {
	if (isNew) {
		return;
	}
	
	if (key == kSpeedLabel) {
		SetSpeed(value.f);
	} else if (key == kDirectionLabel) {
		if (value.f > 0) {
			m_direction = kForward;
		} else if (value.f < 0) {
			m_direction = kReverse;
		}
	}
}