Custom UI Integration
Introduction
Extensions can expose custom UI elements for themes to integrate, this requires support by both an extension and a theme. For theme implementation part, see this page.
Implementation
User Control implementation
- Add new standard WPF UserControl into your project.
- Change base class from
UserControl
toPluginUserControl
You should end up with something like this:
<PluginUserControl x:Class="TestPlugin.TestPluginUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
</Grid>
</PluginUserControl>
public partial class TestPluginUserControl : PluginUserControl
{
public TestPluginUserControl()
{
InitializeComponent();
}
}
Registering custom control
For new control to be recognized by Playnite API and themes call AddCustomElementSupport method in plugin's constructor.
AddCustomElementSupportArgs
contains several arguments:
Property | Description |
---|---|
ElementList | List of element names supported by the plugin. |
SourceName | Plugin source name for element name references and settings bindings. |
Following example will allow themes to reference plugin controls by TestPlugin_TestUserControl1
and TestPlugin_TestUserControl2
names:
AddCustomElementSupport(new AddCustomElementSupportArgs
{
ElementList = new List<string> { "TestUserControl1", "TestUserControl2" },
SourceName = "TestPlugin"
});
Lastly, override GetGameViewControl method. The method is called when theme view template is initialized and plugin control should be "injected" into the view.
Example:
public override Control GetGameViewControl(GetGameViewControlArgs args)
{
if (args.Name == "TestUserControl")
{
return new TestPluginUserControl();
}
return null;
}
Handling data context
Data of currently bound game object can be accessed via PluginUserControl's GameContext
property. If you want to react to data context changes, you can override GameContextChanged method.
Exposing extension settings
You can provide easy way for themes to reference extension settings by calling AddSettingsSupport method in plugin's constructor, similarly to how custom element support is done.
AddSettingsSupport
contains several arguments:
Property | Description |
---|---|
SourceName | Plugin source name for element name references and settings bindings. |
SettingsRoot | Binding root path relative to a plugin object instance. |
SettingsRoot
must be relative binding path to the plugin class. For example, if your plugin class stores settings in Settings
property, then SettingsRoot should be set to just "Settings". If you want themes to dynamically react to settings changes, then you need to implement INotifyPropertyChanged
on your settings object.
Example:
AddSettingsSupport(new AddSettingsSupportArgs
{
SourceName = "TestPlugin",
SettingsRoot = $"binding.path.relative.to.plugin.object"
});
Themes can then reference settings via PluginSettings
markup. See theme integration page for more details.
Custom converters for themes
You can provide custom value converters for themes by calling AddConvertersSupport method in plugin's constructor, similarly to how custom element support is done.
AddConvertersSupport
contains several arguments:
Property | Description |
---|---|
SourceName | Plugin source name used by themes to reference your plugin. |
Converters | List of IValueConverter objects. |
Themes reference converters by their class names so return only once instance of a converter in the converter list.
Theme integration
See theme integration page for more details.
As an extension developer you should provide following information to theme developer:
Source name
: For both general UI integration and settings integration.
Element list
: List of element names that you extension exposes and themes can integrate.
Settings list
: If your extension exposes settings that can be used by themes.
Addon id
: Addon id used in extension manifest, for theme developers to be able to detect if your extension is installed or not.