Creating custom functions
TinyTracker custom functions are external .NET classes loaded from the CustomFunctions folder inside the TinyTracker data directory. Each configured custom-function row becomes one instance of a class that implements ITTCustomCode.
What TinyTracker loads
TinyTracker scans the custom-functions folder and all subfolders for *.dll files. It loads public exported classes that:
- implement
PlasticCheese.TT.ITTCustomCode - are not abstract
- have a public parameterless constructor
The class name stored in TinyTracker is the full type name, including namespace. For example, FranksCustomCode.OpenBugzillaURL.
What you need
- a C# class library targeting
net10.0 - a reference to
TTDefsorTTDefs.dll - at least one public class that implements
ITTCustomCode
TTDefs is the assembly that defines the custom-function contract. The sample FranksCustomCode project in this repo references TTDefs directly.
The interface contract
ITTCustomCode has four properties and three methods:
| Member | Purpose |
|---|---|
Name |
Set by TinyTracker from the label you configure in the UI. |
Shortcut |
Set by TinyTracker from the configured key, from F2 to F12. |
Arguments |
Set by TinyTracker from the arguments field in the UI. |
Description |
Describes the function. It is useful for maintainers, but the current TinyTracker UI does not display it. |
Task Go(IMainForm mf) |
Runs when the configured shortcut key is pressed. |
void OnBeforeWritingToFile(IMainForm mf) |
Runs before TinyTracker writes tracking data. |
void OnAfterWritingToFile(IMainForm mf) |
Runs after TinyTracker writes tracking data. |
The write hooks run for every configured custom-function instance, not only for the function whose shortcut you just pressed. Keep them fast and defensive.
Minimal example
using PlasticCheese.TT;
using System.Threading.Tasks;
namespace MyCustomFunctions
{
public class AddTypedTask : ITTCustomCode
{
public string Shortcut { get; set; }
public string Name { get; set; }
public string Arguments { get; set; }
public string Description => "Adds the current text box contents as a task.";
public Task Go(IMainForm mf)
{
if (!string.IsNullOrWhiteSpace(mf.TextBoxText))
{
mf.BL.AddItem(mf.TextBoxText);
mf.TextBoxText = string.Empty;
}
return Task.CompletedTask;
}
public void OnBeforeWritingToFile(IMainForm mf)
{
}
public void OnAfterWritingToFile(IMainForm mf)
{
}
}
}
Useful members on IMainForm
These members are commonly useful when writing custom code:
mf.selectedItemgets the currently selected task text.mf.TextBoxTextgets or sets the text in the task entry box.mf.BL.AddItem(...)adds a task to the list.mf.selectItem(...)selects a task.mf.showMessageBox(...)shows a message to the user.
Examples in this repo
FranksCustomCode.OpenBugzillaURL
OpenBugzillaURL uses mf.selectedItem, splits it on spaces, takes the last token, and replaces [id] in Arguments before opening the resulting URL in the browser.
Example argument:
http://MyBugzilla.corp/bz/show_bug.cgi?id=[id]
This is useful when your task names end with an issue number.
FranksCustomCode.TrackBugzillaItem
TrackBugzillaItem uses mf.TextBoxText, replaces [TextBoxText] in Arguments, downloads an XML document, extracts values such as cf_mintjobno and bug_severity, and then creates a new task by calling mf.BL.AddItem(...).
Example argument:
http://MyBugzilla.corp/bz/show_bug.cgi?ctype=xml&id=[TextBoxText]
This pattern is useful when you type an issue number into TinyTracker and want the custom function to expand it into a full task name.
Build, copy, and configure
- Build your class library.
- Copy your DLL and any dependent DLLs into TinyTracker's
CustomFunctionsfolder. - Open TinyTracker's custom-function settings and add a row for your function.
- Choose a label, a shortcut from
F2toF12, the full class name, and any arguments your code expects. - Save the settings so TinyTracker reloads the available custom functions.
By default, TinyTracker uses:
%LOCALAPPDATA%\PlasticCheese\TinyTracker\CustomFunctions
If you changed TinyTracker's data path, the custom-functions folder moves with it. The path shown in the Custom Function Settings window is the exact folder TinyTracker scans.
Notes
- TinyTracker ignores bad plugin DLLs and continues loading the rest.
- If a configured class name does not match a loadable type, TinyTracker skips it.
- Each configured row creates a separate instance, so you can reuse the same class with different labels, shortcuts, and arguments.
- Exceptions thrown by custom functions are caught and shown to the user once per function and operation.