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 TTDefs or TTDefs.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.selectedItem gets the currently selected task text.
  • mf.TextBoxText gets 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

  1. Build your class library.
  2. Copy your DLL and any dependent DLLs into TinyTracker's CustomFunctions folder.
  3. Open TinyTracker's custom-function settings and add a row for your function.
  4. Choose a label, a shortcut from F2 to F12, the full class name, and any arguments your code expects.
  5. 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.