By Xiaodong Liang
continued with Timeliner API-part1
Custom Data Source and Task
Using TimeLiner API, you can customize the data source and import your own tasks. This is done through the TimeLiner plug-in. The following shows how to define a custom data source importer, step by step:
- First, we need to define a plug-in implementing TimelinerDataSourceProvider. (At this point, only the skeleton of the class is shown. We’ll fill in more details later.) :
// define a timeliner data source provider
[PluginAttribute("TestTimeLiner", "ADSK")]
[Interface("TimelinerDataSourceProvider", "Navisworks")]
class myTLDataSourceClass : Tl.TimelinerDataSourceProvider
{
// implement abstract property IsAvailable
public override bool IsAvailable { get { return true; } }
// implement abstract method ValidateSettings.
// You do not need to implement the details.
public override Tl.TimelinerValidateSettingsResult ValidateSettings(
Tl.TimelinerDataSource dataSource)
{
Tl.TimelinerValidateSettingsResult result =
new Tl.TimelinerValidateSettingsResult(true);
return result;
}
}
2. Next, override CreateDataSource(). This method provides access to the data source, e.g. showing logging dialog boxes or a file open dialog box. This data source should contain details of the available fields for the Field Selector Dialog box, and added to the AvailableFields collection. In the sample below, we ask the user to select a CSV file. (We assume that before running this sample code, we have created some tasks on the sample model gatehouse.nwd and exported its Timeliner):
// Import data source from a custom csv file
public override Tl.TimelinerDataSource CreateDataSource(string displayName)
{
// create Data Source with a unique name. If the name isn't set, the plugin
// framework provides default name: "New Data Source"
Tl.TimelinerDataSource newDS = new Tl.TimelinerDataSource(displayName);
newDS.DisplayName = "MyTLDSName";
// prompt to select a CSV file
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "select file";
dlg.Filter = "csv files (*.csv)|*.csv";
// set data source's identifier for future reconnect
if (dlg.ShowDialog() == DialogResult.OK)
newDS.ProjectIdentifier = dlg.FileName;
// populate the AvailableFields we wish people to map. Theoretically you
// could provide no field mappings and always map the same fields. In this
// sample, we ignore the fields
// newDS.AvailableFields.Add(
// new Tl.TimelinerDataSourceField("Task Name", "Task Name"));
// must have Plugin.Id which should be a property on the subclass
// TimelinerDataSourceProvider. The plugin framework finds the plugin to
// automate for the data source
newDS.DataSourceProviderId = base.Id;
// version, whatever you like
newDS.DataSourceProviderVersion = 1.0;
// some user friendly name, ideally matching the name of the plugin itself
newDS.DataSourceProviderName = "TestTimeLiner";
return newDS;
}
3. Override ImportTasksCore(). This should do the actual work of importing the tasks. Autodesk® Navisworks® software will call it when Rebuild/Synchronize the custom data source. We need to create and return a TimelinerImportTasksResult and implement its RootTask. RootTask is the entire hierarchy of tasks and its children we want to import:
// implementing ImportTasksCore()
// This is the part which does the actual work importing.
protected override Tl.TimelinerImportTasksResult ImportTasksCore(
Tl.TimelinerDataSource dataSource)
{
// create a TimelinerImportTasksResult and root task
Tl.TimelinerImportTasksResult tr = new Tl.TimelinerImportTasksResult();
tr.RootTask = new Tl.TimelinerTask();
// Set true if the data source was configured to set
// the SimulationTaskTypeName on the tasks imported
tr.TaskTypeWasSet = true;
//The Name of the simulation type to which this belongs
tr.RootTask.SimulationTaskTypeName = "TestTimeLiner";
// The ExternalId should be set
tr.RootTask.ExternalId = Tl.TimelinerTask.DataSourceRootTaskIdentifier;
//start to enumerate the hierarchy of the tasks from the external source
//and add children task below the RootTask. For each task look at the
//mappings provided on the supplied datasource and obtain the field
//specified by that mapping by looking at its id
//Or you may know the mapping and never want the user to set
//read the source data. In this sampl, ProjectIdentifier is the CSV file
StreamReader sr = new StreamReader(dataSource.ProjectIdentifier);
//ignore the header row of CSV file
string strline = sr.ReadLine();
while (!sr.EndOfStream)
{
strline = sr.ReadLine(); //each row
// suppose the CSV file is separated by comma
string[] _values = strline.Split(',');
//create sub task
Tl.TimelinerTask oSubTask = new Tl.TimelinerTask();
//we have known the sequence of each column
oSubTask.DisplayName = _values[1];
oSubTask.IsActualEnabled = _values[3] == "1" ? true : false;
if (!string.IsNullOrEmpty(_values[4]))
oSubTask.ActualStartDate = Convert.ToDateTime(_values[4]);
if (!string.IsNullOrEmpty(_values[5]))
oSubTask.ActualEndDate = Convert.ToDateTime(_values[5]);
oSubTask.IsPlannedEnabled = _values[6] == "1" ? true : false;
if (!string.IsNullOrEmpty(_values[7]))
oSubTask.PlannedStartDate = Convert.ToDateTime(_values[7]);
if (!string.IsNullOrEmpty(_values[8]))
oSubTask.PlannedEndDate = Convert.ToDateTime(_values[8]);
oSubTask.SimulationTaskTypeName = _values[9];
oSubTask.ExternalId = _values[12];
//add the task to root task
newTR.RootTask.Children.Add(oSubTask);
}
sr.Close();
return newTR;
}
Once the plug-in is loaded, we will see a new data source in the drop down menu. Add one CSV file and build the hierarchy. The tasks are imported.