-
Notifications
You must be signed in to change notification settings - Fork 40
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-net
branch of this repository - Create a new project using the
WPF User Control Library
template - Add
Shared
project 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:
-
uWidgets
project is a WPF application. Consider it as an entry point for the whole application. -
Shared
project 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.json
contains application's settings, ex. current theme and language. You can access it by usingIAppSettingsProvider
. -
layout.json
contains 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.