-
Notifications
You must be signed in to change notification settings - Fork 62
uWidgets Contribution Guide
uWidget is a continuation of the MontereyRainmeter project. It is a C# solution, built using .NET Core 6 and the WPF framework.
This guide will provide all the information you need to contribute your custom widget to our application.
- Start by cloning the
2.0-netbranch of this repository - Create a new project using the
WPF User Control Librarytemplate - Add
Sharedproject as a dependency - Change the project's output path to
..\..\uWidgets\bin\Debug\Widgets\
YourProject.csproj
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>..\..\uWidgets\bin\Debug\Widgets\</OutputPath>
</PropertyGroup>
uWidgets solution contains of two main projects:
-
uWidgetsproject is a WPF application. Consider it as an entry point for the whole application. -
Sharedproject is a class library. It contains classes and interfaces that may be useful for building custom widgets.
There are two .json files the project uses to store settings:
-
appSettings.jsoncontains application's settings, ex. current theme and language. You can access it by usingIAppSettingsProvider. -
layout.jsoncontains an array, where each element represents widget's layout and settings. You can access your widget's settings by usingIWidgetSettingsProvider.
Widget class is located in Shared project, represents a WPF window that will contain some content. It wraps around your UserControl and takes responsibility for things like:
- Resizing
- Moving
- Theming
- Context menus
Here's an example of widget project's structure:
Clock/
Views/
AnalogClock.xaml
AnalogClock.xaml.cs
DigitalClock.xaml
DigitalClock.xaml.cs
Models/
ClockViewModel.cs
ClockSettings.cs
Your project can contain multiple view classes. Each of them must be inherited from the UserControl class.
Here's example of a view class:
DigitalClock.xaml
<UserControl ...>
<!-- Your widget layout here -->
</UserControl>
DigitalClock.xaml.cs
public partial class DigitalClock : UserControl
{
public DigitalClock()
{
InitializeComponent();
}
}
Your project must contain exactly one Settings class, inherited from the WidgetSettings class.
Here's example of Settings class:
public class ClockSettings : WidgetSettings
{
public bool ShowSeconds { get; set; }
public bool ShowAmPm { get; set; }
}
These settings will be stored in layout.json class, and you will be able to access them using IWidgetSettingsProvider
Your project must contain exactly one ViewModel class, implementing INotifyPropertyChanged interface.
ViewModel class represents current state of the widgets. This class is also used in Data Binding.
That means, you can access any property you had described in that class, from your .xaml view, like this:
ClockViewModel.cs
public class ClockViewModel : INotifyPropertyChanged
{
public DateTime Time { get; set; }
public string TimeString => Time.ToString("hh:mm:ss");
}
DigitalClock.xaml
<UserControl d:DataContext="{d:DesignInstance Type=models:ClockViewModel}" ...>
<TextBlock Text="{Binding TimeString}" />
</UserControl>
You can access application's and widget's settings using IAppSettingsProvider and IWidgetSettignsProvider, like this:
public class ClockViewModel : INotifyPropertyChanged
{
public DateTime Time { get; set; }
public string TimeString => Time.ToString(timeFormat);
private string timeFormat;
public ClockViewModel(IAppSettingsProvider appSettingsProvider, IWidgetSettingsProvider widgetSettingsProvider)
{
var showSeconds = widgetSettingsProvider.ShowSeconds;
timeFormat = showSeconds ? "hh:mm:ss" : "hh:mm";
}
}
Both of these interfaces provide Updated events. Subscribe to them to update your content if these data were changed.
To update your view you need to raise PropertyChanged event with a name of the property that was changed. There's also a quick way to do it:
protected virtual void Update()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
}
Passing string.Empty as property name will notify that all ViewModel properties were changed.
Add an array element into layout.json, like that:
{
"Type": "<Your project name>",
"Subtype": "<Your UserControl class name>",
"Id": "<Unique GUID>",
"X": <int>,
"Y": <int>,
"Columns": <int>,
"Rows": <int>,
<your other settings, described in Settings class>
}
Now, when you start uWidgets project, you will see your widget and be able to interact with it
Create a Pull Request so we can merge your widget into our solution.
We don't have any specific guidelines for Pull Requests yet, but we encourage clear and concise descriptions of your widget.