tbIDE Package

The tbIDE package is the addin SDK for the twinBASIC IDE. An addin is a Standard DLL that the IDE loads at start-up; the DLL exports one factory function, returns one object implementing the AddIn contract, and from there everything happens through the Host object the IDE passes in. The package itself is type-only — every public symbol is an interface or a CoClass; the actual implementations live in the twinBASIC IDE binary, and the addin DLL binds against the type declarations and lets the IDE marshal calls into its implementations at run time.

The package is a built-in compiler package shipped with twinBASIC. It is added to addin projects automatically; you do not need to add it manually through Project → References.

Building and loading an addin

An addin project has three distinguishing settings:

  • Build type: Standard DLL.
  • Build path: ${IdePath}\addins\${Architecture}\${ProjectName}.${FileExtension}. The output drops directly into the IDE’s addins\Win32\ or addins\Win64\ folder, where the IDE scans for addins on start-up.
  • Compiler-package reference to tbIDE (added to the project’s references with isCompilerPackage: true, publisher: TWINBASIC-COMPILER, symbolId: tbIDE). This is the binding between the DLL’s compile-time types and the IDE’s run-time implementations.

The DLL must export one function — the entry point the IDE calls when it discovers and loads the addin:

Module MainModule
    [DllExport]
    Public Function tbCreateCompilerAddin(ByVal Host As Host) As AddIn
        Return New MyAddIn(Host)
    End Function
End Module

The returned object must implement AddIn. The IDE releases the object when the addin is disabled or the IDE shuts down, which lets the addin clean up through Class_Terminate.

A minimal addin class:

Private Class MyAddIn
    Implements AddIn

    Private WithEvents Host As Host

    Public Sub New(ByVal Host As Host)
        Set Me.Host = Host
    End Sub

    Private Property Get AddIn_Name() As String
        Return "My AddIn"
    End Property

    Private Sub Host_OnProjectLoaded()
        Host.DebugConsole.PrintText "Hello from My AddIn!"
    End Sub
End Class

The WithEvents Host As Host pattern is how the addin subscribes to IDE lifecycle events (OnProjectLoaded, OnChangedActiveEditor, OnChangedTheme). Almost every meaningful addin sets up its toolbar buttons and tool windows inside the OnProjectLoaded handler — that is the first moment the IDE is fully ready to accept extensibility commands.

The class catalogue

The package’s twenty-four .twin files declare one interface-and-CoClass pair each (plus one concrete Class), grouped here by role for orientation. Every CoClass except AddinTimer is handed to the addin by the IDE — never instantiated with New.

Entry point and root API

Project, editors, and the virtual file system

IDE UI surface

Tool-window DOM and events

The four Html* classes are the addin’s keyhole into the DOM inside a tool window. All four are declared with [COMExtensible(True)] — see Dynamic DOM property resolution.

Singletons

Dynamic DOM property resolution

The four Html* classes that carry the [COMExtensible(True)] attribute — HtmlElementProperties, HtmlElementProperty, HtmlEventProperties, HtmlEventProperty — accept arbitrary property names that are resolved against the underlying DOM element (or event object) at run time. None of style, innerText, chart, editor, listview, value, target, key, index, …, are declared statically on the interfaces — they are all resolved dynamically through the COM-extensible Item(name) default member.

So:

With element.ChildDomElements.Add("mySeparator", "h1").Properties
    .style.textAlign = "center"
    .style.color     = "white"
    .innerText       = "Section heading"
End With

reads at run time as:

.Item("style").Item("textAlign").Value = "center"
.Item("style").Item("color").Value     = "white"
.Item("innerText").Value               = "Section heading"

The compiler does not validate the property names; they are forwarded as strings to the IDE’s tool-window renderer. The accepted set is every DOM property of the underlying tag — standard HTML attributes, every CSS-style property under .style.…, plus any custom-widget-specific surface like .chart.data.datasets(0).borderWidth on a "chartjs" element or .editor.setOption(...) on a "monaco" element. The reference does not enumerate them — defer to MDN for standard DOM property names, to Chart.js for chartjs widgets, to Monaco’s documentation for monaco widgets, and to the matching samples below for the IDE-specific listview / virtuallistview surface.

Tool-window DOM tags

HtmlElements.Add takes a TagName string. Standard HTML tags ("div", "span", "input", "h1", "label", "img", …) work as expected; in addition, the IDE provides four custom-widget tags:

  • "chartjs" — wraps Chart.js. The element surfaces a .chart property whose sub-properties mirror Chart.js’s data / options / config namespaces. See sample 11.
  • "monaco" — embeds an instance of the Monaco editor (the same editor the IDE itself uses for code panes). The element surfaces an .editor property with setOption, setValue, getValue, and AddEventListener (note: event listeners attach to .editor, not to the DOM element). See sample 12.
  • "listview" — the IDE’s built-in listview widget. The element surfaces a .listview property with addItem, removeItem, getItem, setShowScrollbarV / setShowScrollbarH, and the events onClickItem / onDblClickItem. See sample 13.
  • "virtuallistview" — a virtual variant of the listview suitable for huge data sets (millions of rows). The element surfaces the same .listview property plus setItemCount and the asynchronous onAsyncGetItemHTML event (the listener responds via eventInfo.setAsyncResult("<html>")); call .listview.notifyChangedItem(idx) to invalidate the internal cache for one row when its underlying data changes. See sample 14.

The full per-widget property and method surface is documented by each widget’s home project; this package wraps them through the same [COMExtensible(True)] mechanism described above.

Where the samples live

Six worked addins ship in the twinBASIC samples folder. They are the canonical reference for “how to use the package end-to-end” and are referenced throughout the per-class pages.

Sample Project What it teaches
10 WaynesWorldAddInTest1 The kitchen-sink walkthrough — toolbar setup, a single big tool window populated with 22 styled div-buttons that each exercise a different Host.* capability. Start here.
11 WaynesWorldCPUMonitorTest1 AddinTimer + a "chartjs" custom-widget tool window driving a live line chart.
12 WaynesWorldMonacoEditorTest1 A "monaco" custom-widget tool window: an in-window Monaco editor with setValue / getValue and a content-change listener.
13 WaynesListViewAddIn A "listview" custom-widget tool window with ApplyCss, double-click-to-remove behaviour, and inline-HTML raiseEvent() for custom event names.
14 WaynesVirtualListViewAddIn A "virtuallistview" with 5,000,000 rows backed by onAsyncGetItemHTML / setAsyncResult / notifyChangedItem.
15 tbGlobalSearchAddIn1 A full-blown Global Search addin: virtual-FS traversal (For Each over Folder), text reading with comment-stripping (File.ReadText), editor navigation (Editors.Open), persistent options via GetSetting / SaveSetting.