diff --git a/Bloxstrap/App.xaml b/Bloxstrap/App.xaml index ae4bfac..2029b34 100644 --- a/Bloxstrap/App.xaml +++ b/Bloxstrap/App.xaml @@ -11,6 +11,8 @@ + + pack://application:,,,/Resources/Fonts/#Rubik Light diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 8e88aa5..bb30ff6 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -25,9 +25,14 @@ + + + + + @@ -49,6 +54,7 @@ + @@ -59,6 +65,7 @@ + diff --git a/Bloxstrap/Enums/BootstrapperStyle.cs b/Bloxstrap/Enums/BootstrapperStyle.cs index 5c5f6fd..c638858 100644 --- a/Bloxstrap/Enums/BootstrapperStyle.cs +++ b/Bloxstrap/Enums/BootstrapperStyle.cs @@ -10,6 +10,7 @@ ByfronDialog, [EnumName(StaticName = "Bloxstrap")] FluentDialog, - FluentAeroDialog + FluentAeroDialog, + CustomDialog } } diff --git a/Bloxstrap/Enums/CustomThemeTemplate.cs b/Bloxstrap/Enums/CustomThemeTemplate.cs new file mode 100644 index 0000000..6497907 --- /dev/null +++ b/Bloxstrap/Enums/CustomThemeTemplate.cs @@ -0,0 +1,8 @@ +namespace Bloxstrap.Enums +{ + public enum CustomThemeTemplate + { + Blank, + Simple + } +} diff --git a/Bloxstrap/Exceptions/CustomThemeException.cs b/Bloxstrap/Exceptions/CustomThemeException.cs new file mode 100644 index 0000000..68ad0a1 --- /dev/null +++ b/Bloxstrap/Exceptions/CustomThemeException.cs @@ -0,0 +1,60 @@ +using Bloxstrap.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Exceptions +{ + internal class CustomThemeException : Exception + { + /// + /// The exception message in English (for logging) + /// + public string EnglishMessage { get; } = null!; + + public CustomThemeException(string translationString) + : base(Strings.ResourceManager.GetStringSafe(translationString)) + { + EnglishMessage = Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")); + } + + public CustomThemeException(Exception innerException, string translationString) + : base(Strings.ResourceManager.GetStringSafe(translationString), innerException) + { + EnglishMessage = Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")); + } + + public CustomThemeException(string translationString, params object?[] args) + : base(string.Format(Strings.ResourceManager.GetStringSafe(translationString), args)) + { + EnglishMessage = string.Format(Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")), args); + } + + public CustomThemeException(Exception innerException, string translationString, params object?[] args) + : base(string.Format(Strings.ResourceManager.GetStringSafe(translationString), args), innerException) + { + EnglishMessage = string.Format(Strings.ResourceManager.GetStringSafe(translationString, new CultureInfo("en-GB")), args); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(GetType().ToString()); + + if (!string.IsNullOrEmpty(Message)) + sb.Append($": {Message}"); + + if (!string.IsNullOrEmpty(EnglishMessage) && Message != EnglishMessage) + sb.Append($" ({EnglishMessage})"); + + if (InnerException != null) + sb.Append($"\r\n ---> {InnerException}\r\n "); + + if (StackTrace != null) + sb.Append($"\r\n{StackTrace}"); + + return sb.ToString(); + } + } +} diff --git a/Bloxstrap/Extensions/BootstrapperStyleEx.cs b/Bloxstrap/Extensions/BootstrapperStyleEx.cs index 3802264..693c78e 100644 --- a/Bloxstrap/Extensions/BootstrapperStyleEx.cs +++ b/Bloxstrap/Extensions/BootstrapperStyleEx.cs @@ -13,7 +13,8 @@ BootstrapperStyle.ProgressDialog, BootstrapperStyle.LegacyDialog2011, BootstrapperStyle.LegacyDialog2008, - BootstrapperStyle.VistaDialog + BootstrapperStyle.VistaDialog, + BootstrapperStyle.CustomDialog }; } } diff --git a/Bloxstrap/Extensions/CustomThemeTemplateEx.cs b/Bloxstrap/Extensions/CustomThemeTemplateEx.cs new file mode 100644 index 0000000..4088f02 --- /dev/null +++ b/Bloxstrap/Extensions/CustomThemeTemplateEx.cs @@ -0,0 +1,10 @@ +namespace Bloxstrap.Extensions +{ + static class CustomThemeTemplateEx + { + public static string GetFileName(this CustomThemeTemplate template) + { + return $"CustomBootstrapperTemplate_{template}.xml"; + } + } +} diff --git a/Bloxstrap/Models/Persistable/Settings.cs b/Bloxstrap/Models/Persistable/Settings.cs index d640fc3..a239f31 100644 --- a/Bloxstrap/Models/Persistable/Settings.cs +++ b/Bloxstrap/Models/Persistable/Settings.cs @@ -17,6 +17,7 @@ namespace Bloxstrap.Models.Persistable public bool UseFastFlagManager { get; set; } = true; public bool WPFSoftwareRender { get; set; } = false; public bool EnableAnalytics { get; set; } = true; + public string? SelectedCustomTheme { get; set; } = null; // integration configuration public bool EnableActivityTracking { get; set; } = true; diff --git a/Bloxstrap/Paths.cs b/Bloxstrap/Paths.cs index 43d4a1c..1205d67 100644 --- a/Bloxstrap/Paths.cs +++ b/Bloxstrap/Paths.cs @@ -22,6 +22,7 @@ public static string Integrations { get; private set; } = ""; public static string Versions { get; private set; } = ""; public static string Modifications { get; private set; } = ""; + public static string CustomThemes { get; private set; } = ""; public static string Application { get; private set; } = ""; @@ -37,6 +38,7 @@ Integrations = Path.Combine(Base, "Integrations"); Versions = Path.Combine(Base, "Versions"); Modifications = Path.Combine(Base, "Modifications"); + CustomThemes = Path.Combine(Base, "CustomThemes"); Application = Path.Combine(Base, $"{App.ProjectName}.exe"); } diff --git a/Bloxstrap/Resource.cs b/Bloxstrap/Resource.cs index 46c8e82..612d846 100644 --- a/Bloxstrap/Resource.cs +++ b/Bloxstrap/Resource.cs @@ -21,5 +21,10 @@ namespace Bloxstrap await stream.CopyToAsync(memoryStream); return memoryStream.ToArray(); } + + public static async Task GetString(string name) + { + return Encoding.UTF8.GetString(await Get(name)); + } } } diff --git a/Bloxstrap/Resources/CustomBootstrapperSchema.json b/Bloxstrap/Resources/CustomBootstrapperSchema.json new file mode 100644 index 0000000..44b6631 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperSchema.json @@ -0,0 +1,521 @@ +{ + "Elements": { + "FrameworkElement": { + "IsCreatable": false, + "Attributes": { + "Name": "string", + "Visibility": "Visibility", + "IsEnabled": "bool", + "Margin": "Thickness", + "Height": "double", + "Width": "double", + "HorizontalAlignment": "HorizontalAlignment", + "VerticalAlignment": "VerticalAlignment", + "RenderTransform": "Transform", + "LayoutTransform": "Transform", + "Opacity": "double", + "OpacityMask": "Brush", + "RenderTransformOrigin": "Point", + "Panel.ZIndex": "int", + "Grid.Row": "int", + "Grid.RowSpan": "int", + "Grid.Column": "int", + "Grid.ColumnSpan": "int" + } + }, + "Control": { + "SuperClass": "FrameworkElement", + "IsCreatable": false, + "Attributes": { + "Padding": "Thickness", + "BorderThickness": "Thickness", + "Foreground": "Brush", + "Background": "Brush", + "BorderBrush": "Brush", + "FontSize": "double", + "FontWeight": "FontWeight", + "FontStyle": "FontStyle", + "FontFamily": "FontFamily" + } + }, + "BloxstrapCustomBootstrapper": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "Version": "int", + "Theme": "Theme", + "Title": "string", + "IgnoreTitleBarInset": "bool", + "WindowCornerPreference": "WindowCornerPreference" + } + }, + "TitleBar": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "ShowMinimize": "bool", + "ShowClose": "bool", + "Title": "string" + } + }, + "Button": { + "SuperClass": "Control", + "IsCreatable": true, + "Attributes": { + "Content": "object" + } + }, + "RangeBase": { + "SuperClass": "Control", + "IsCreatable": false, + "Attributes": { + "Value": "double", + "Maximum": "double" + } + }, + "ProgressBar": { + "SuperClass": "RangeBase", + "IsCreatable": true, + "Attributes": { + "IsIndeterminate": "bool", + "CornerRadius": "CornerRadius", + "IndicatorCornerRadius": "CornerRadius" + } + }, + "ProgressRing": { + "SuperClass": "RangeBase", + "IsCreatable": true, + "Attributes": { + "IsIndeterminate": "bool" + } + }, + "TextBlock": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Text": "string", + "Foreground": "Brush", + "Background": "Brush", + "FontSize": "double", + "FontWeight": "FontWeight", + "FontStyle": "FontStyle", + "FontFamily": "FontFamily", + "LineHeight": "double", + "LineStackingStrategy": "LineStackingStrategy", + "TextAlignment": "TextAlignment", + "TextTrimming": "TextTrimming", + "TextWrapping": "TextWrapping", + "TextDecorations": "TextDecorations", + "IsHyphenationEnabled": "bool", + "BaselineOffset": "double", + "Padding": "Thickness" + } + }, + "MarkdownTextBlock": { + "SuperClass": "TextBlock", + "IsCreatable": true, + "Attributes": {} + }, + "Image": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Stretch": "Stretch", + "StretchDirection": "StretchDirection", + "Source": "ImageSource", + "IsAnimated": "bool" + } + }, + "Grid": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "RowDefinitions": "object", + "ColumnDefinitions": "object" + } + }, + "StackPanel": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Orientation": "Orientation" + } + }, + "Border": { + "SuperClass": "FrameworkElement", + "IsCreatable": true, + "Attributes": { + "Background": "Brush", + "BorderBrush": "Brush", + "BorderThickness": "Thickness", + "Padding": "Thickness", + "CornerRadius": "CornerRadius" + } + }, + "RowDefinition": { + "IsCreatable": true, + "Attributes": { + "Height": "GridLength", + "MinHeight": "double", + "MaxHeight": "double" + } + }, + "ColumnDefinition": { + "IsCreatable": true, + "Attributes": { + "Width": "GridLength", + "MinWidth": "double", + "MaxWidth": "double" + } + }, + "ScaleTransform": { + "IsCreatable": true, + "Attributes": { + "ScaleX": "double", + "ScaleY": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "SkewTransform": { + "IsCreatable": true, + "Attributes": { + "AngleX": "double", + "AngleY": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "RotateTransform": { + "IsCreatable": true, + "Attributes": { + "Angle": "double", + "CenterX": "double", + "CenterY": "double" + } + }, + "TranslateTransform": { + "IsCreatable": true, + "Attributes": { + "X": "double", + "Y": "double" + } + }, + "Brush": { + "IsCreatable": false, + "Attributes": { + "Opacity": "double" + } + }, + "SolidColorBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "Color": "Color" + } + }, + "ImageBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "AlignmentX": "AlignmentX", + "AlignmentY": "AlignmentY", + "Stretch": "Stretch", + "TileMode": "TileMode", + "ViewboxUnits": "BrushMappingMode", + "ViewportUnits": "BrushMappingMode", + "Viewbox": "Rect", + "Viewport": "Rect", + "ImageSource": "ImageSource" + } + }, + "LinearGradientBrush": { + "SuperClass": "Brush", + "IsCreatable": true, + "Attributes": { + "StartPoint": "Point", + "EndPoint": "Point", + "ColorInterpolationMode": "ColorInterpolationMode", + "MappingMode": "BrushMappingMode", + "SpreadMethod": "GradientSpreadMethod" + } + }, + "GradientStop": { + "IsCreatable": true, + "Attributes": { + "Color": "Color", + "Offset": "double" + } + }, + "Shape": { + "SuperClass": "FrameworkElement", + "IsCreatable": false, + "Attributes": { + "Fill": "Brush", + "Stroke": "Brush", + "Stretch": "Stretch", + "StrokeDashCap": "PenLineCap", + "StrokeDashOffset": "double", + "StrokeEndLineCap": "PenLineCap", + "StrokeLineJoin": "PenLineJoin", + "StrokeMiterLimit": "double", + "StrokeStartLineCap": "PenLineCap", + "StrokeThickness": "double" + } + }, + "Ellipse": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": {} + }, + "Line": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": { + "X1": "double", + "X2": "double", + "Y1": "double", + "Y2": "double" + } + }, + "Rectangle": { + "SuperClass": "Shape", + "IsCreatable": true, + "Attributes": { + "RadiusX": "double", + "RadiusY": "double" + } + }, + "BlurEffect": { + "IsCreatable": true, + "Attributes": { + "KernelType": "KernelType", + "Radius": "double", + "RenderingBias": "RenderingBias" + } + }, + "DropShadowEffect": { + "IsCreatable": true, + "Attributes": { + "BlurRadius": "double", + "Direction": "double", + "Opacity": "double", + "ShadowDepth": "double", + "RenderingBias": "RenderingBias", + "Color": "Color" + } + } + }, + "Types": { + "string": {}, + "bool": { + "Values": [ + "True", + "False" + ] + }, + "int": {}, + "double": {}, + "object": { "CanHaveElement": true }, + "Thickness": {}, + "Rect": {}, + "Point": {}, + "CornerRadius": {}, + "Brush": { "CanHaveElement": true }, + "Color": {}, + "ImageSource": {}, + "Transform": { "CanHaveElement": true }, + "FontFamily": {}, + "GridLength": {}, + "Visibility": { + "Values": [ + "Visible", + "Hidden", + "Collapsed" + ] + }, + "HorizontalAlignment": { + "Values": [ + "Left", + "Center", + "Right", + "Stretch" + ] + }, + "VerticalAlignment": { + "Values": [ + "Top", + "Center", + "Bottom", + "Stretch" + ] + }, + "Theme": { + "Values": [ + "Default", + "Dark", + "Light" + ] + }, + "FontWeight": { + "Values": [ + "Thin", + "ExtraLight", + "UltraLight", + "Medium", + "Normal", + "Regular", + "DemiBold", + "SemiBold", + "Bold", + "ExtraBold", + "UltraBold", + "Black", + "Heavy", + "ExtraBlack", + "ExtraHeavy" + ] + }, + "FontStyle": { + "Values": [ + "Normal", + "Italic", + "Oblique" + ] + }, + "LineStackingStrategy": { + "Values": [ + "BlockLineHeight", + "MaxHeight" + ] + }, + "TextAlignment": { + "Values": [ + "Left", + "Right", + "Center", + "Justify" + ] + }, + "TextTrimming": { + "Values": [ + "None", + "CharacterEllipsis", + "WordEllipsis" + ] + }, + "TextWrapping": { + "Values": [ + "WrapWithOverflow", + "NoWrap", + "Wrap" + ] + }, + "TextDecorations": { + "Values": [ + "Baseline", + "OverLine", + "Strikethrough", + "Underline" + ] + }, + "Stretch": { + "Values": [ + "None", + "Fill", + "Uniform", + "UniformToFill" + ] + }, + "StretchDirection": { + "Values": [ + "UpOnly", + "DownOnly", + "Both" + ] + }, + "AlignmentX": { + "Values": [ + "Left", + "Center", + "Right" + ] + }, + "AlignmentY": { + "Values": [ + "Top", + "Center", + "Bottom" + ] + }, + "TileMode": { + "Values": [ + "None", + "FlipX", + "FlipY", + "FlipXY", + "Tile" + ] + }, + "BrushMappingMode": { + "Values": [ + "Absolute", + "RelativeToBoundingBox" + ] + }, + "ColorInterpolationMode": { + "Values": [ + "ScRgbLinearInterpolation", + "SRgbLinearInterpolation" + ] + }, + "GradientSpreadMethod": { + "Values": [ + "Pad", + "Reflect", + "Repeat" + ] + }, + "PenLineCap": { + "Values": [ + "Flat", + "Square", + "Round", + "Triangle" + ] + }, + "PenLineJoin": { + "Values": [ + "Miter", + "Bevel", + "Round" + ] + }, + "KernelType": { + "Values": [ + "Gaussian", + "Box" + ] + }, + "RenderingBias": { + "Values": [ + "Performance", + "Quality" + ] + }, + "Orientation": { + "Values": [ + "Horizontal", + "Vertical" + ] + }, + "WindowCornerPreference": { + "Values": [ + "Default", + "DoNotRound", + "Round", + "RoundSmall" + ] + } + } +} \ No newline at end of file diff --git a/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml b/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml new file mode 100644 index 0000000..99efce9 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperTemplate_Blank.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml b/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml new file mode 100644 index 0000000..7664806 --- /dev/null +++ b/Bloxstrap/Resources/CustomBootstrapperTemplate_Simple.xml @@ -0,0 +1,9 @@ + + + + + + + +