();
- });
+
return result;
}
- private static TabItem TextTab()
+ private static TabItem HtmlTab()
{
return new TabItem
{
Header = "Text",
- Content = new StackPanel
- {
- Orientation = Orientation.Vertical,
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Gap = 8,
- Width = 120,
- Children = new Controls
- {
- new TextBlock
- {
- Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
- TextWrapping = TextWrapping.Wrap,
- TextAlignment = TextAlignment.Center,
- },
- new TextBlock
- {
- Text = "Italic text.",
- FontStyle = FontStyle.Italic,
- TextAlignment = TextAlignment.Left,
- },
- new TextBlock
- {
- Text = "Bold text.",
- FontWeight = FontWeight.Bold,
- TextAlignment = TextAlignment.Right,
- },
- new TextBox
- {
- Text = "A non-wrapping text box. Lorem ipsum dolor sit amet.",
- TextWrapping = TextWrapping.NoWrap,
- },
- new TextBox
- {
- AcceptsReturn = true,
- Text = "A wrapping text box. " +
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt. " +
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
- TextWrapping = TextWrapping.Wrap,
- MaxHeight = 100,
- },
- }
- },
+ Content = new ScrollViewer()
+ {
+ CanScrollHorizontally = false,
+ Content = new StackPanel()
+ {
+ Margin = new Thickness(10),
+ Orientation = Orientation.Vertical,
+ Gap = 4,
+ Children = new Controls
+ {
+ new TextBlock
+ {
+ Text = "TextBlock",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A control for displaying text.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new TextBlock
+ {
+ Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
+ FontSize = 11
+ },
+ new TextBlock
+ {
+ Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
+ FontSize = 11,
+ FontWeight = FontWeight.Medium
+ },
+ new TextBlock
+ {
+ Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
+ FontSize = 11,
+ FontWeight = FontWeight.Bold
+ },
+ new TextBlock
+ {
+ Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
+ FontSize = 11,
+ FontStyle = FontStyle.Italic,
+ },
+ new TextBlock
+ {
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "HtmlLabel",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A label capable of displaying HTML content",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new HtmlLabel
+ {
+ Background = SolidColorBrush.Parse("#CCCCCC"),
+ Padding = new Thickness(5),
+ Text = @"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.
+ Header Level 2
+
+
+ - Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+ - Aliquam tincidunt mauris eu risus.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.
+
+ Header Level 3
+
+
+ - Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+ - Aliquam tincidunt mauris eu risus.
+
"
+ }
+ }
+ }
+ }
};
}
- private static TabItem ImagesTab()
+ private static TabItem TextTab()
{
- ScrollBar size;
-
return new TabItem
{
- Header = "Images",
- Content = new StackPanel
- {
- Orientation = Orientation.Vertical,
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Gap = 8,
- Children = new Controls
- {
- (size = new ScrollBar
- {
- Minimum = 100,
- Maximum = 400,
- Value = 100,
- Orientation = Orientation.Horizontal,
- }),
- new ScrollViewer
- {
- Width = 200,
- Height = 200,
- CanScrollHorizontally = true,
- Content = new Image
- {
- Source = new Bitmap("github_icon.png"),
- [!Image.WidthProperty] = size[!ScrollBar.ValueProperty],
- [!Image.HeightProperty] = size[!ScrollBar.ValueProperty],
- },
- },
- new ProgressBar
- {
- [!ProgressBar.MinimumProperty] = size[!ScrollBar.MinimumProperty],
- [!ProgressBar.MaximumProperty] = size[!ScrollBar.MaximumProperty],
- [!ProgressBar.ValueProperty] = size[!ScrollBar.ValueProperty],
- }
- }
- },
+ Header = "Input",
+ Content = new ScrollViewer()
+ {
+ Content = new StackPanel
+ {
+ Margin = new Thickness(10),
+ Orientation = Orientation.Vertical,
+ Gap = 4,
+ Children = new Controls
+ {
+ new TextBlock
+ {
+ Text = "TextBox",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A text box control",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new TextBox { Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", Width = 200 },
+ new TextBox { AcceptsReturn = true, TextWrapping = TextWrapping.Wrap, Width = 200, Height = 150, Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." },
+ new TextBlock
+ {
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "CheckBox",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A check box control",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new CheckBox { IsChecked = true, Margin = new Thickness(0, 0, 0, 5), Content = "Checked" },
+ new CheckBox { IsChecked = false, Content = "Unchecked" },
+ new TextBlock
+ {
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "RadioButton",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A radio button control",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new RadioButton { IsChecked = true, Content = "Option 1" },
+ new RadioButton { IsChecked = false, Content = "Option 2" },
+ new RadioButton { IsChecked = false, Content = "Option 3" },
+ }
+ }
+ }
};
}
+
private static TabItem ListsTab()
{
- ListBox listBox;
-
return new TabItem
{
Header = "Lists",
- Content = new StackPanel
- {
- DataTemplates = new DataTemplates
- {
- new DataTemplate- (x =>
- new StackPanel
- {
- Children = new Controls
- {
- new TextBlock { Text = x.Name, FontSize = 24 },
- new TextBlock { Text = x.Value },
- }
- })
- },
- Orientation = Orientation.Horizontal,
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Gap = 8,
- Children = new Controls
- {
- new TreeView
- {
- Name = "treeView",
- Items = treeData,
- },
- (listBox = new ListBox
- {
- Items = listBoxData,
- MaxHeight = 300,
- }),
- new DropDown
- {
- Items = listBoxData,
- SelectedItem = listBoxData[0],
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
- },
+ Content = new ScrollViewer()
+ {
+ CanScrollHorizontally = false,
+ Content = new StackPanel
+ {
+ HorizontalAlignment = HorizontalAlignment.Left,
+ Orientation = Orientation.Vertical,
+ VerticalAlignment = VerticalAlignment.Top,
+ Gap = 4,
+ Margin = new Thickness(10),
+ DataTemplates = new DataTemplates
+ {
+ new DataTemplate
- (x =>
+ new StackPanel
+ {
+ Gap = 4,
+ Orientation = Orientation.Horizontal,
+ Children = new Controls
+ {
+ new Image { Width = 50, Height = 50, Source = new Bitmap("github_icon.png") },
+ new TextBlock { Text = x.Name, FontSize = 18 }
+ }
+ })
+ },
+ Children = new Controls
+ {
+ new TextBlock
+ {
+ Text = "ListBox",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A list box control.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new ListBox
+ {
+ BorderThickness = 2,
+ Items = s_listBoxData,
+ Height = 300,
+ Width = 300,
+ },
+ new TextBlock
+ {
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "TreeView",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A tree view control.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new TreeView
+ {
+ Name = "treeView",
+ Items = s_treeData,
+ Height = 300,
+ BorderThickness = 2,
+ Width = 300,
+ }
+ }
+ },
+ }
};
}
+ private static TabItem ImagesTab()
+ {
+ var imageDeck = new Deck
+ {
+ Width = 400,
+ Height = 400,
+ Transition = new PageSlide(TimeSpan.FromSeconds(0.25)),
+ Items = new[]
+ {
+ new Image { Source = new Bitmap("github_icon.png"), Width = 400, Height = 400 },
+ new Image { Source = new Bitmap("pattern.jpg"), Width = 400, Height = 400 },
+ }
+ };
+
+ imageDeck.AutoSelect = true;
+
+ var next = new Button
+ {
+ VerticalAlignment = VerticalAlignment.Center,
+ Padding = new Thickness(20),
+ Content = new Perspex.Controls.Shapes.Path
+ {
+ Data = StreamGeometry.Parse("M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"),
+ Fill = Brushes.Black
+ }
+ };
+
+ var prev = new Button
+ {
+ VerticalAlignment = VerticalAlignment.Center,
+ Padding = new Thickness(20),
+ Content = new Perspex.Controls.Shapes.Path
+ {
+ Data = StreamGeometry.Parse("M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"),
+ Fill = Brushes.Black
+ }
+ };
+
+ prev.Click += (s, e) =>
+ {
+ if (imageDeck.SelectedIndex == 0)
+ imageDeck.SelectedIndex = 1;
+ else
+ imageDeck.SelectedIndex--;
+ };
+
+ next.Click += (s, e) =>
+ {
+ if (imageDeck.SelectedIndex == 1)
+ imageDeck.SelectedIndex = 0;
+ else
+ imageDeck.SelectedIndex++;
+ };
+
+ return new TabItem
+ {
+ Header = "Images",
+ Content = new ScrollViewer
+ {
+ Content = new StackPanel
+ {
+ HorizontalAlignment = HorizontalAlignment.Left,
+ Orientation = Orientation.Vertical,
+ VerticalAlignment = VerticalAlignment.Top,
+ Gap = 4,
+ Margin = new Thickness(10),
+ Children = new Controls
+ {
+ new TextBlock
+ {
+ Text = "Deck",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "An items control that displays its items as pages that fill the controls.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new StackPanel
+ {
+ Name = "deckVisual",
+ Orientation = Orientation.Horizontal,
+ Gap = 4,
+ Children = new Controls
+ {
+ prev,
+ imageDeck,
+ next
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
private static TabItem LayoutTab()
{
return new TabItem
{
Header = "Layout",
- Content = new Grid
- {
- ColumnDefinitions = new ColumnDefinitions
- {
- new ColumnDefinition(1, GridUnitType.Star),
- new ColumnDefinition(1, GridUnitType.Star),
- },
- Margin = new Thickness(50),
- Children = new Controls
- {
- new StackPanel
- {
- Orientation = Orientation.Vertical,
- Gap = 8,
- Children = new Controls
+ Content = new ScrollViewer
+ {
+ Content = new StackPanel
+ {
+ HorizontalAlignment = HorizontalAlignment.Left,
+ Orientation = Orientation.Vertical,
+ VerticalAlignment = VerticalAlignment.Top,
+ Gap = 4,
+ Margin = new Thickness(10),
+ Children = new Controls
+ {
+ new TextBlock
+ {
+ Text = "Grid",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "Lays out child controls according to a grid.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new Grid
+ {
+ Width = 600,
+ ColumnDefinitions = new ColumnDefinitions
+ {
+ new ColumnDefinition(1, GridUnitType.Star),
+ new ColumnDefinition(1, GridUnitType.Star),
+ },
+
+ RowDefinitions = new RowDefinitions
+ {
+ new RowDefinition(1, GridUnitType.Auto),
+ new RowDefinition(1, GridUnitType.Auto)
+ },
+ Children = new Controls
+ {
+
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FF5722"),
+ [Grid.ColumnSpanProperty] = 2,
+ Height = 200,
+ Margin = new Thickness(2.5)
+ },
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FF5722"),
+ [Grid.RowProperty] = 1,
+ Height = 100,
+ Margin = new Thickness(2.5)
+ },
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FF5722"),
+ [Grid.RowProperty] = 1,
+ [Grid.ColumnProperty] = 1,
+ Height = 100,
+ Margin = new Thickness(2.5)
+ },
+ },
+ },
+ new TextBlock
+ {
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "StackPanel",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A panel which lays out its children horizontally or vertically.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ new StackPanel
+ {
+ Orientation = Orientation.Vertical,
+ Gap = 4,
+ Width = 300,
+ Children = new Controls
+ {
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FFC107"),
+ Height = 50,
+ },
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FFC107"),
+ Height = 50,
+ },
+ new Rectangle
+ {
+ Fill = SolidColorBrush.Parse("#FFC107"),
+ Height = 50,
+ },
+ }
+ },
+ new TextBlock
{
- new Button { HorizontalAlignment = HorizontalAlignment.Left, Content = "Left Aligned" },
- new Button { HorizontalAlignment = HorizontalAlignment.Center, Content = "Center Aligned" },
- new Button { HorizontalAlignment = HorizontalAlignment.Right, Content = "Right Aligned" },
- new Button { HorizontalAlignment = HorizontalAlignment.Stretch, Content = "Stretch" },
+ Margin = new Thickness(0, 40, 0, 0),
+ Text = "Canvas",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
},
- [Grid.ColumnProperty] = 0,
- },
- new StackPanel
- {
- Orientation = Orientation.Horizontal,
- Gap = 8,
- Children = new Controls
+ new TextBlock
{
- new Button { VerticalAlignment = VerticalAlignment.Top, Content = "Top Aligned" },
- new Button { VerticalAlignment = VerticalAlignment.Center, Content = "Center Aligned" },
- new Button { VerticalAlignment = VerticalAlignment.Bottom, Content = "Bottom Aligned" },
- new Button { VerticalAlignment = VerticalAlignment.Stretch, Content = "Stretch" },
+ Text = "A panel which lays out its children by explicit coordinates.",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
},
- [Grid.ColumnProperty] = 1,
- },
- },
- }
+ new Canvas
+ {
+ Background = Brushes.Yellow,
+ Width = 300,
+ Height = 400,
+ Children = new Controls
+ {
+ new Rectangle
+ {
+ Fill = Brushes.Blue,
+ Width = 63,
+ Height = 41,
+ [Canvas.LeftProperty] = 40,
+ [Canvas.TopProperty] = 31,
+ },
+ new Ellipse
+ {
+ Fill = Brushes.Green,
+ Width = 58,
+ Height = 58,
+ [Canvas.LeftProperty] = 130,
+ [Canvas.TopProperty] = 79,
+ },
+ }
+ },
+ }
+ }
+ }
};
}
@@ -562,70 +731,88 @@ namespace TestApplication
var result = new TabItem
{
Header = "Animations",
- Content = new Grid
+ Content = new StackPanel
{
- ColumnDefinitions = new ColumnDefinitions
- {
- new ColumnDefinition(1, GridUnitType.Star),
- new ColumnDefinition(1, GridUnitType.Star),
- },
- RowDefinitions = new RowDefinitions
- {
- new RowDefinition(1, GridUnitType.Star),
- new RowDefinition(GridLength.Auto),
- },
+ HorizontalAlignment = HorizontalAlignment.Left,
+ Orientation = Orientation.Vertical,
+ VerticalAlignment = VerticalAlignment.Top,
+ Gap = 4,
+ Margin = new Thickness(10),
Children = new Controls
{
- (border1 = new Border
- {
- Width = 100,
- Height = 100,
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Background = Brushes.Crimson,
- RenderTransform = new RotateTransform(),
- Child = new TextBox
- {
- Background = Brushes.White,
- Text = "Hello!",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- },
- }),
- (border2 = new Border
- {
- Width = 100,
- Height = 100,
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- Background = Brushes.Coral,
- Child = new Image
- {
- Source = new Bitmap("github_icon.png"),
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- },
- RenderTransform = (rotate = new RotateTransform
- {
- PropertyTransitions = new PropertyTransitions
- {
- RotateTransform.AngleProperty.Transition(500),
- }
- }),
- PropertyTransitions = new PropertyTransitions
- {
- Rectangle.WidthProperty.Transition(300),
- Rectangle.HeightProperty.Transition(1000),
- },
- [Grid.ColumnProperty] = 1,
- }),
- (button1 = new Button
- {
- HorizontalAlignment = HorizontalAlignment.Center,
- Content = "Animate",
- [Grid.ColumnProperty] = 1,
- [Grid.RowProperty] = 1,
- }),
+ new TextBlock
+ {
+ Text = "Animations",
+ FontWeight = FontWeight.Medium,
+ FontSize = 20,
+ Foreground = SolidColorBrush.Parse("#212121"),
+ },
+ new TextBlock
+ {
+ Text = "A few animations showcased below",
+ FontSize = 13,
+ Foreground = SolidColorBrush.Parse("#727272"),
+ Margin = new Thickness(0, 0, 0, 10)
+ },
+ (button1 = new Button
+ {
+ Content = "Animate",
+ Width = 120,
+ [Grid.ColumnProperty] = 1,
+ [Grid.RowProperty] = 1,
+ }),
+ new Canvas
+ {
+ Children = new Controls
+ {
+ (border1 = new Border
+ {
+ Width = 100,
+ Height = 100,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ Background = Brushes.Crimson,
+ RenderTransform = new RotateTransform(),
+ Child = new TextBox
+ {
+ Background = Brushes.White,
+ Text = "Hello!",
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ },
+ [Canvas.LeftProperty] = 100,
+ [Canvas.TopProperty] = 100,
+ }),
+ (border2 = new Border
+ {
+ Width = 100,
+ Height = 100,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ Background = Brushes.Coral,
+ Child = new Image
+ {
+ Source = new Bitmap("github_icon.png"),
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ },
+ RenderTransform = (rotate = new RotateTransform
+ {
+ PropertyTransitions = new PropertyTransitions
+ {
+ RotateTransform.AngleProperty.Transition(500),
+ }
+ }),
+ PropertyTransitions = new PropertyTransitions
+ {
+ Layoutable.WidthProperty.Transition(300),
+ Layoutable.HeightProperty.Transition(1000),
+ },
+ [Canvas.LeftProperty] = 400,
+ [Canvas.TopProperty] = 100,
+ }),
+ }
+ }
},
},
};
diff --git a/samples/TestApplication/Properties/AssemblyInfo.cs b/samples/TestApplication/Properties/AssemblyInfo.cs
index 5e8029017d..4560d26d17 100644
--- a/samples/TestApplication/Properties/AssemblyInfo.cs
+++ b/samples/TestApplication/Properties/AssemblyInfo.cs
@@ -1,4 +1,7 @@
-using System.Reflection;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -10,7 +13,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestApplication")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyCopyright("Copyright \u00A9 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/samples/TestApplication/TestApplication.csproj b/samples/TestApplication/TestApplication.csproj
index 1a3a6287fc..4ccecb2cd0 100644
--- a/samples/TestApplication/TestApplication.csproj
+++ b/samples/TestApplication/TestApplication.csproj
@@ -35,18 +35,6 @@
4
-
- ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.dll
- True
-
-
- ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll
- True
-
-
- ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
- True
-
@@ -72,9 +60,21 @@
..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
+
+ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.dll
+
+
+ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll
+
+
+ ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
+
+
+
+
@@ -83,8 +83,12 @@
+
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}
+ Perspex.Cairo
+
- {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ {D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
@@ -103,6 +107,10 @@
{7062AE20-5DCC-4442-9645-8195BDECE63E}
Perspex.Diagnostics
+
+ {5FB2B005-0A7F-4DAD-ADD4-3ED01444E63D}
+ Perspex.HtmlRenderer
+
{62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
@@ -132,11 +140,11 @@
Perspex.Themes.Default
- {3e908f67-5543-4879-a1dc-08eace79b3cd}
+ {3E908F67-5543-4879-A1DC-08EACE79B3CD}
Perspex.Direct2D1
- {811a76cf-1cf6-440f-963b-bbe31bd72a82}
+ {811A76CF-1CF6-440F-963B-BBE31BD72A82}
Perspex.Win32
@@ -144,6 +152,10 @@
PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/samples/TestApplication/html.htm b/samples/TestApplication/html.htm
new file mode 100644
index 0000000000..85da0cdb87
--- /dev/null
+++ b/samples/TestApplication/html.htm
@@ -0,0 +1,128 @@
+
+
+ Intro
+
+
+
+
+ HTML Renderer Project - Perspex port
+
+ Beta support
+
+
+
+
+
+ Lightweight (~300K).
+ High performance and low memory footprint.
+ Extendable and configurable.
+
+
+ Limitations
+
+
+ - All HTML end tags marked as
+ optional should be there. No problem with tags marked as forbidden.
+
+
+
+ On the roadmap
+ Of course it's not quite finished yet. Here are some of the important things to
+ do.
+
+ - Better performance
+ - Support of position CSS property
+ - Support of height and min-height CSS property
+ - Better tables support, especially layouts
+ - Support image align
+ - Handle :hover selector
+ - Selection by shift+arrows
+ - Better HTML tag parsing (optional closing tags)
+ - More styles support
+
+
+ Vision
+
+
+ - Most complete static HTML Renderer (no java script).
+ - Commercial web browser performance level.
+
+
+
+ 2015 - Nikita Tsukanov (Perspex Port)
+
+
+
+ https://perspex.github.io/
+
+
+
+ 2012 - Arthur Teplitzki
+
+
+ http://TheArtOfDev.com
+
+
+ 2009 - Jose Manuel Menendez Poo
+
+
+ www.menendezpoo.com
+
+
+
+
\ No newline at end of file
diff --git a/samples/TestApplication/pattern.jpg b/samples/TestApplication/pattern.jpg
new file mode 100644
index 0000000000..72b35e0692
Binary files /dev/null and b/samples/TestApplication/pattern.jpg differ
diff --git a/samples/XamlTestApplication/App.config b/samples/XamlTestApplication/App.config
index bfc5697e01..5ce331f23a 100644
--- a/samples/XamlTestApplication/App.config
+++ b/samples/XamlTestApplication/App.config
@@ -1,7 +1,7 @@
-
+
diff --git a/samples/XamlTestApplication/App.cs b/samples/XamlTestApplication/App.cs
index 4762a4892e..d0c6f59040 100644
--- a/samples/XamlTestApplication/App.cs
+++ b/samples/XamlTestApplication/App.cs
@@ -1,16 +1,19 @@
-namespace XamlTestApplication
-{
- using System;
- using Perspex;
- using Perspex.Themes.Default;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex;
+using Perspex.Themes.Default;
+namespace XamlTestApplication
+{
public class App : Application
{
public App()
{
- this.RegisterServices();
- this.InitializeSubsystems((int)Environment.OSVersion.Platform);
- this.Styles = new DefaultTheme();
+ RegisterServices();
+ InitializeSubsystems((int)Environment.OSVersion.Platform);
+ Styles = new DefaultTheme();
}
}
}
diff --git a/samples/XamlTestApplication/MainViewModel.cs b/samples/XamlTestApplication/MainViewModel.cs
index 57db4848c1..450c8f422f 100644
--- a/samples/XamlTestApplication/MainViewModel.cs
+++ b/samples/XamlTestApplication/MainViewModel.cs
@@ -1,15 +1,18 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Collections.Generic;
+using ReactiveUI;
+
namespace XamlTestApplication
{
- using System.Collections.Generic;
- using ReactiveUI;
-
public class MainViewModel : ReactiveObject
{
- private string name;
+ private string _name;
public MainViewModel()
{
- Name = "Jos Manuel";
+ Name = "Jos\u00E9 Manuel";
People = new List
{
new Person("a little bit of Monica in my life"),
@@ -24,8 +27,8 @@ namespace XamlTestApplication
public string Name
{
- get { return name; }
- set { this.RaiseAndSetIfChanged(ref name, value); }
+ get { return _name; }
+ set { this.RaiseAndSetIfChanged(ref _name, value); }
}
public List People { get; set; }
@@ -33,17 +36,17 @@ namespace XamlTestApplication
public class Person
{
- private string name;
+ private string _name;
public Person(string name)
{
- this.name = name;
+ _name = name;
}
public string Name
{
- get { return name; }
- set { name = value; }
+ get { return _name; }
+ set { _name = value; }
}
}
}
\ No newline at end of file
diff --git a/samples/XamlTestApplication/Program.cs b/samples/XamlTestApplication/Program.cs
index e24f228086..d115b67809 100644
--- a/samples/XamlTestApplication/Program.cs
+++ b/samples/XamlTestApplication/Program.cs
@@ -1,35 +1,38 @@
-namespace XamlTestApplication
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Diagnostics;
+using System.Windows.Threading;
+using Perspex;
+using Perspex.Collections;
+using Perspex.Controls;
+using Perspex.Controls.Templates;
+using ReactiveUI;
+using XamlTestApplication.Views;
+
+namespace XamlTestApplication
{
- using System;
- using System.Diagnostics;
- using System.Windows.Threading;
- using Perspex;
- using Perspex.Collections;
- using Perspex.Controls;
- using Perspex.Controls.Templates;
- using ReactiveUI;
- using Views;
-
- class Item
+ internal class Item
{
public string Name { get; set; }
public string Value { get; set; }
}
- class Node
+ internal class Node
{
public Node()
{
- this.Children = new PerspexList();
+ Children = new PerspexList();
}
public string Name { get; set; }
public PerspexList Children { get; set; }
}
- class Program
+ internal class Program
{
- static void Main()
+ private static void Main()
{
var foo = Dispatcher.CurrentDispatcher;
@@ -46,10 +49,10 @@
var testCommand = ReactiveCommand.Create();
testCommand.Subscribe(_ => Debug.WriteLine("Test command executed."));
-
+
var window = new MainWindow();
window.Show();
Application.Current.Run(window);
- }
+ }
}
}
diff --git a/samples/XamlTestApplication/Properties/AssemblyInfo.cs b/samples/XamlTestApplication/Properties/AssemblyInfo.cs
index 5e8029017d..4560d26d17 100644
--- a/samples/XamlTestApplication/Properties/AssemblyInfo.cs
+++ b/samples/XamlTestApplication/Properties/AssemblyInfo.cs
@@ -1,4 +1,7 @@
-using System.Reflection;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -10,7 +13,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestApplication")]
-[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyCopyright("Copyright \u00A9 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/samples/XamlTestApplication/Views/MainWindow.cs b/samples/XamlTestApplication/Views/MainWindow.cs
index 18760d9601..dc218641bf 100644
--- a/samples/XamlTestApplication/Views/MainWindow.cs
+++ b/samples/XamlTestApplication/Views/MainWindow.cs
@@ -1,20 +1,23 @@
-namespace XamlTestApplication.Views
-{
- using System;
- using System.Globalization;
- using System.IO;
- using System.Reflection;
- using System.Resources;
- using OmniXaml;
- using Perspex.Controls;
- using Perspex.Diagnostics;
- using Perspex.Markup.Xaml;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using OmniXaml;
+using Perspex.Controls;
+using Perspex.Diagnostics;
+using Perspex.Markup.Xaml;
+namespace XamlTestApplication.Views
+{
public class MainWindow : Window
{
public MainWindow()
{
- this.InitializeComponent();
+ InitializeComponent();
DevTools.Attach(this);
}
diff --git a/samples/XamlTestApplication/Views/MainWindow.xaml b/samples/XamlTestApplication/Views/MainWindow.paml
similarity index 84%
rename from samples/XamlTestApplication/Views/MainWindow.xaml
rename to samples/XamlTestApplication/Views/MainWindow.paml
index 3294edb8b0..2c4525eb13 100644
--- a/samples/XamlTestApplication/Views/MainWindow.xaml
+++ b/samples/XamlTestApplication/Views/MainWindow.paml
@@ -1,19 +1,21 @@
-
-
-
-
-
+ Title="Perspex Test Application" Height="350" Width="525" SizeToContent="WidthAndHeight" >
+
+
+
+
+
-
+
@@ -24,9 +26,9 @@
-
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.
+
Bold text.
@@ -100,7 +102,13 @@
-
+
+
+
+
+
+
+
-
+
Debug
@@ -9,7 +9,7 @@
Properties
XamlTestApplication
XamlTestApplication
- v4.5.1
+ v4.5
512
@@ -36,59 +36,43 @@
4
-
- ..\..\packages\Glass.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\Glass.dll
- True
-
-
- ..\..\packages\OmniXaml.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\OmniXaml.dll
+
+
+
+
+ ..\..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll
True
-
+
+
+
+
+
+
+
..\..\packages\Serilog.1.5.9\lib\net45\Serilog.dll
- True
-
+
..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll
- True
-
+
..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
- True
-
- ..\..\packages\Sprache.SuperJMN.2.0.0.50\lib\portable-net451+netcore451+wpa81\Sprache.dll
- True
+
+ ..\..\packages\Sprache.2.0.0.47\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll
-
-
-
-
+
..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll
- True
-
+
..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
- True
-
+
..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
- True
-
+
..\..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll
- True
-
- ..\..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll
- True
-
-
-
-
-
-
-
@@ -101,40 +85,36 @@
-
- {415e048e-4611-4815-9cf2-d774e29079ac}
- NGenerics
-
- {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ {D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
- {799a7bb5-3c2c-48b6-85a7-406a12c420da}
+ {799A7BB5-3C2C-48B6-85A7-406A12C420DA}
Perspex.Application
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
- {7062ae20-5dcc-4442-9645-8195bdece63e}
+ {7062AE20-5DCC-4442-9645-8195BDECE63E}
Perspex.Diagnostics
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
- {42472427-4774-4c81-8aff-9f27b8e31721}
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
@@ -142,27 +122,27 @@
Perspex.ReactiveUI
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
- {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
+ {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}
Perspex.Themes.Default
- {3e53a01a-b331-47f3-b828-4a5717e77a24}
+ {3E53A01A-B331-47F3-B828-4A5717E77A24}
Perspex.Markup.Xaml
- {3e908f67-5543-4879-a1dc-08eace79b3cd}
+ {3E908F67-5543-4879-A1DC-08EACE79B3CD}
Perspex.Direct2D1
- {811a76cf-1cf6-440f-963b-bbe31bd72a82}
+ {811A76CF-1CF6-440F-963B-BBE31BD72A82}
Perspex.Win32
@@ -173,9 +153,9 @@
-
+
Designer
-
+
diff --git a/samples/XamlTestApplication/packages.config b/samples/XamlTestApplication/packages.config
index 601727ed56..0fafe14cb6 100644
--- a/samples/XamlTestApplication/packages.config
+++ b/samples/XamlTestApplication/packages.config
@@ -1,7 +1,5 @@
-
-
@@ -10,5 +8,5 @@
-
+
\ No newline at end of file
diff --git a/src/Gtk/Perspex.Cairo/CairoExtensions.cs b/src/Gtk/Perspex.Cairo/CairoExtensions.cs
index dd09e7e46b..fa66837194 100644
--- a/src/Gtk/Perspex.Cairo/CairoExtensions.cs
+++ b/src/Gtk/Perspex.Cairo/CairoExtensions.cs
@@ -1,8 +1,5 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Perspex.Cairo
{
@@ -10,6 +7,11 @@ namespace Perspex.Cairo
public static class CairoExtensions
{
+ public static Cairo.Color ToCairo(this Perspex.Media.Color color)
+ {
+ return new Cairo.Color(color.R / 255.0, color.G / 255.0, color.B / 255.0, color.A / 255.0);
+ }
+
public static Cairo.Matrix ToCairo(this Matrix m)
{
return new Cairo.Matrix(m.M11, m.M12, m.M21, m.M22, m.M31, m.M32);
@@ -25,6 +27,11 @@ namespace Perspex.Cairo
return new Cairo.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
}
+ public static Rect ToPerspex(this Cairo.Rectangle rect)
+ {
+ return new Rect(rect.X, rect.Y, rect.Width, rect.Height);
+ }
+
public static Rect ToPerspex(this Pango.Rectangle rect)
{
return new Rect(
@@ -36,37 +43,7 @@ namespace Perspex.Cairo
public static Pango.Weight ToCairo(this Perspex.Media.FontWeight weight)
{
- if (weight == Perspex.Media.FontWeight.Light)
- {
- return Pango.Weight.Light;
- }
-
- if (weight == Perspex.Media.FontWeight.Normal || weight == Perspex.Media.FontWeight.Regular)
- {
- return Pango.Weight.Normal;
- }
-
- if (weight == Perspex.Media.FontWeight.DemiBold || weight == Perspex.Media.FontWeight.Medium)
- {
- return Pango.Weight.Semibold;
- }
-
- if (weight == Perspex.Media.FontWeight.Bold)
- {
- return Pango.Weight.Bold;
- }
-
- if (weight == Perspex.Media.FontWeight.UltraBold || weight == Perspex.Media.FontWeight.ExtraBold)
- {
- return Pango.Weight.Ultrabold;
- }
-
- if (weight == Perspex.Media.FontWeight.Black || weight == Perspex.Media.FontWeight.Heavy || weight == Perspex.Media.FontWeight.UltraBlack)
- {
- return Pango.Weight.Heavy;
- }
-
- return Pango.Weight.Ultralight;
+ return (Pango.Weight)weight;
}
public static Pango.Alignment ToCairo(this Perspex.Media.TextAlignment alignment)
diff --git a/src/Gtk/Perspex.Cairo/CairoPlatform.cs b/src/Gtk/Perspex.Cairo/CairoPlatform.cs
index 827014afb4..f25aadda95 100644
--- a/src/Gtk/Perspex.Cairo/CairoPlatform.cs
+++ b/src/Gtk/Perspex.Cairo/CairoPlatform.cs
@@ -1,49 +1,48 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Cairo.Media;
+using Perspex.Cairo.Media.Imaging;
+using Perspex.Media;
+using Perspex.Platform;
+using Splat;
namespace Perspex.Cairo
{
- using System;
+ using System.IO;
using global::Cairo;
- using Perspex.Cairo.Media;
- using Perspex.Cairo.Media.Imaging;
- using Perspex.Media;
- using Perspex.Platform;
- using Perspex.Threading;
- using Splat;
public class CairoPlatform : IPlatformRenderInterface
{
- private static CairoPlatform instance = new CairoPlatform();
+ private static readonly CairoPlatform s_instance = new CairoPlatform();
+
+ private static Pango.Context s_pangoContext = CreatePangoContext();
public static void Initialize()
{
var locator = Locator.CurrentMutable;
- locator.Register(() => instance, typeof(IPlatformRenderInterface));
+ locator.Register(() => s_instance, typeof(IPlatformRenderInterface));
}
public IBitmapImpl CreateBitmap(int width, int height)
{
- return new BitmapImpl(new ImageSurface(Format.Argb32, width, height));
+ return new BitmapImpl(new Gdk.Pixbuf(Gdk.Colorspace.Rgb, true, 32, width, height));
}
public IFormattedTextImpl CreateFormattedText(
- string text,
- string fontFamily,
- double fontSize,
+ string text,
+ string fontFamily,
+ double fontSize,
FontStyle fontStyle,
TextAlignment textAlignment,
Perspex.Media.FontWeight fontWeight)
{
- return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight);
+ return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight);
}
public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height)
{
- Locator.CurrentMutable.RegisterConstant(this.GetPangoContext(handle), typeof(Pango.Context));
return new Renderer(handle, width, height);
}
@@ -59,22 +58,22 @@ namespace Perspex.Cairo
public IBitmapImpl LoadBitmap(string fileName)
{
- ImageSurface result = new ImageSurface(fileName);
- return new BitmapImpl(result);
+ var pixbuf = new Gdk.Pixbuf(fileName);
+
+ return new BitmapImpl(pixbuf);
+ }
+
+ public IBitmapImpl LoadBitmap(Stream stream)
+ {
+ var pixbuf = new Gdk.Pixbuf(stream);
+
+ return new BitmapImpl(pixbuf);
}
- private Pango.Context GetPangoContext(IPlatformHandle handle)
+ private static Pango.Context CreatePangoContext()
{
- switch (handle.HandleDescriptor)
- {
- case "GtkWindow":
- var window = GLib.Object.GetObject(handle.Handle) as Gtk.Window;
- return window.PangoContext;
- default:
- throw new NotSupportedException(string.Format(
- "Don't know how to get a Pango Context from a '{0}'.",
- handle.HandleDescriptor));
- }
+ Gtk.Application.Init();
+ return new Gtk.Invisible().CreatePangoContext();
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/BrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/BrushImpl.cs
new file mode 100644
index 0000000000..76ad34b19a
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/BrushImpl.cs
@@ -0,0 +1,17 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo
+{
+ public abstract class BrushImpl : IDisposable
+ {
+ public Pattern PlatformBrush { get; protected set; }
+
+ public void Dispose()
+ {
+ if (this.PlatformBrush != null)
+ this.PlatformBrush.Dispose();
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs b/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
index 39477d2817..03e5ab6879 100644
--- a/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
+++ b/src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
@@ -1,19 +1,16 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2013 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Linq;
+using System.Reactive.Disposables;
+using Perspex.Cairo.Media.Imaging;
+using Perspex.Media;
+
namespace Perspex.Cairo.Media
{
- using System;
- using System.Reactive.Disposables;
- using Perspex.Cairo.Media.Imaging;
- using Perspex.Media;
- using Perspex.Platform;
- using Splat;
+ using Perspex.Media.Imaging;
using Cairo = global::Cairo;
- using IBitmap = Perspex.Media.Imaging.IBitmap;
- using System.Collections.Generic;
///
/// Draws using Direct2D1.
@@ -23,12 +20,7 @@ namespace Perspex.Cairo.Media
///
/// The cairo context.
///
- private Cairo.Context context;
-
- ///
- /// The cairo surface.
- ///
- private Cairo.Surface surface;
+ private readonly Cairo.Context _context;
///
/// Initializes a new instance of the class.
@@ -36,9 +28,8 @@ namespace Perspex.Cairo.Media
/// The target surface.
public DrawingContext(Cairo.Surface surface)
{
- this.surface = surface;
- this.context = new Cairo.Context(surface);
- this.CurrentTransform = Matrix.Identity;
+ _context = new Cairo.Context(surface);
+ CurrentTransform = Matrix.Identity;
}
///
@@ -47,50 +38,68 @@ namespace Perspex.Cairo.Media
/// The GDK drawable.
public DrawingContext(Gdk.Drawable drawable)
{
- this.Drawable = drawable;
- this.context = Gdk.CairoHelper.Create(drawable);
- this.CurrentTransform = Matrix.Identity;
+ _context = Gdk.CairoHelper.Create(drawable);
+ CurrentTransform = Matrix.Identity;
}
+ ///
+ /// Gets the current transform of the drawing context.
+ ///
public Matrix CurrentTransform
{
- get;
- private set;
- }
-
- public Gdk.Drawable Drawable
- {
- get;
- private set;
- }
+ get; }
///
/// Ends a draw operation.
///
public void Dispose()
{
- this.context.Dispose();
-
- // if (this.surface is Cairo.Win32Surface)
- // {
- if (this.surface != null)
- this.surface.Dispose();
- // }
+ _context.Dispose();
}
+ ///
+ /// Draws a bitmap image.
+ ///
+ /// The bitmap image.
+ /// The opacity to draw with.
+ /// The rect in the image to draw.
+ /// The rect in the output to draw to.
public void DrawImage(IBitmap bitmap, double opacity, Rect sourceRect, Rect destRect)
{
var impl = bitmap.PlatformImpl as BitmapImpl;
var size = new Size(impl.PixelWidth, impl.PixelHeight);
- var scaleX = destRect.Size.Width / sourceRect.Size.Width;
- var scaleY = destRect.Size.Height / sourceRect.Size.Height;
-
- this.context.Save();
- this.context.Scale(scaleX, scaleY);
- this.context.SetSourceSurface(impl.Surface, (int)sourceRect.X, (int)sourceRect.Y);
- this.context.Rectangle(sourceRect.ToCairo());
- this.context.Fill();
- this.context.Restore();
+ var scale = new Vector(destRect.Width / sourceRect.Width, destRect.Height / sourceRect.Height);
+
+ _context.Save();
+ _context.Scale(scale.X, scale.Y);
+ destRect /= scale;
+
+ if (opacityOverride < 1.0f) {
+ _context.PushGroup ();
+ Gdk.CairoHelper.SetSourcePixbuf (
+ _context,
+ impl.Surface,
+ -sourceRect.X + destRect.X,
+ -sourceRect.Y + destRect.Y);
+
+ _context.Rectangle (destRect.ToCairo ());
+ _context.Fill ();
+ _context.PopGroupToSource ();
+ _context.PaintWithAlpha (opacityOverride);
+ } else {
+ _context.PushGroup ();
+ Gdk.CairoHelper.SetSourcePixbuf (
+ _context,
+ impl.Surface,
+ -sourceRect.X + destRect.X,
+ -sourceRect.Y + destRect.Y);
+
+ _context.Rectangle (destRect.ToCairo ());
+ _context.Fill ();
+ _context.PopGroupToSource ();
+ _context.PaintWithAlpha (opacityOverride);
+ }
+ _context.Restore();
}
///
@@ -99,15 +108,16 @@ namespace Perspex.Cairo.Media
/// The stroke pen.
/// The first point of the line.
/// The second point of the line.
- public void DrawLine(Pen pen, Perspex.Point p1, Perspex.Point p2)
+ public void DrawLine(Pen pen, Point p1, Point p2)
{
var size = new Rect(p1, p2).Size;
- this.SetBrush(pen.Brush, size);
- this.context.LineWidth = pen.Thickness;
- this.context.MoveTo(p1.ToCairo());
- this.context.LineTo(p2.ToCairo());
- this.context.Stroke();
+ using (var p = SetPen(pen, size))
+ {
+ _context.MoveTo(p1.ToCairo());
+ _context.LineTo(p2.ToCairo());
+ _context.Stroke();
+ }
}
///
@@ -116,55 +126,32 @@ namespace Perspex.Cairo.Media
/// The fill brush.
/// The stroke pen.
/// The geometry.
- public void DrawGeometry(Perspex.Media.Brush brush, Perspex.Media.Pen pen, Perspex.Media.Geometry geometry)
+ public void DrawGeometry(Brush brush, Pen pen, Geometry geometry)
{
var impl = geometry.PlatformImpl as StreamGeometryImpl;
- var clone = new Queue(impl.Operations);
-
- using (var pop = this.PushTransform(impl.Transform))
+
+ using (var pop = PushTransform(impl.Transform))
{
- while (clone.Count > 0)
- {
- var current = clone.Dequeue();
-
- if (current is BeginOp)
- {
- var bo = current as BeginOp;
- this.context.MoveTo(bo.Point.ToCairo());
- }
- else if (current is LineToOp)
- {
- var lto = current as LineToOp;
- this.context.LineTo(lto.Point.ToCairo());
- }
- else if (current is EndOp)
- {
- if (((EndOp)current).IsClosed)
- this.context.ClosePath();
- }
- else if (current is CurveToOp)
- {
- var cto = current as CurveToOp;
- this.context.CurveTo(cto.Point.ToCairo(), cto.Point2.ToCairo(), cto.Point3.ToCairo());
- }
- }
-
+ _context.AppendPath(impl.Path);
+
if (brush != null)
{
- this.SetBrush(brush, geometry.Bounds.Size);
-
- if (pen != null)
- this.context.FillPreserve();
- else
- this.context.Fill();
+ using (var b = SetBrush(brush, geometry.Bounds.Size))
+ {
+ if (pen != null)
+ _context.FillPreserve();
+ else
+ _context.Fill();
+ }
}
+ }
-
- if (pen != null)
- {
- this.SetPen(pen, geometry.Bounds.Size);
- this.context.Stroke();
- }
+ if (pen != null)
+ {
+ using (var p = SetPen(pen, geometry.Bounds.Size))
+ {
+ _context.Stroke();
+ }
}
}
@@ -175,9 +162,11 @@ namespace Perspex.Cairo.Media
/// The rectangle bounds.
public void DrawRectange(Pen pen, Rect rect, float cornerRadius)
{
- this.SetPen(pen, rect.Size);
- this.context.Rectangle(rect.ToCairo());
- this.context.Stroke();
+ using (var p = SetPen(pen, rect.Size))
+ {
+ _context.Rectangle(rect.ToCairo ());
+ _context.Stroke();
+ }
}
///
@@ -189,10 +178,12 @@ namespace Perspex.Cairo.Media
public void DrawText(Brush foreground, Point origin, FormattedText text)
{
var layout = ((FormattedTextImpl)text.PlatformImpl).Layout;
- this.SetBrush(foreground, new Size(0, 0));
-
- this.context.MoveTo(origin.X, origin.Y);
- Pango.CairoHelper.ShowLayout(this.context, layout);
+ _context.MoveTo(origin.X, origin.Y);
+
+ using (var b = SetBrush(foreground, new Size(0, 0)))
+ {
+ Pango.CairoHelper.ShowLayout(_context, layout);
+ }
}
///
@@ -200,11 +191,13 @@ namespace Perspex.Cairo.Media
///
/// The brush.
/// The rectangle bounds.
- public void FillRectange(Perspex.Media.Brush brush, Rect rect, float cornerRadius)
+ public void FillRectange(Brush brush, Rect rect, float cornerRadius)
{
- this.SetBrush(brush, rect.Size);
- this.context.Rectangle(rect.ToCairo());
- this.context.Fill();
+ using (var b = SetBrush(brush, rect.Size))
+ {
+ _context.Rectangle(rect.ToCairo ());
+ _context.Fill();
+ }
}
///
@@ -214,10 +207,10 @@ namespace Perspex.Cairo.Media
/// A disposable used to undo the clip rectangle.
public IDisposable PushClip(Rect clip)
{
- this.context.Rectangle(clip.ToCairo());
- this.context.Clip();
+ _context.Rectangle(clip.ToCairo());
+ _context.Clip();
- return Disposable.Create(() => this.context.ResetClip());
+ return Disposable.Create(() => _context.ResetClip());
}
///
@@ -227,8 +220,15 @@ namespace Perspex.Cairo.Media
/// A disposable used to undo the opacity.
public IDisposable PushOpacity(double opacity)
{
- // TODO: Implement
- return Disposable.Empty;
+ var tmp = opacityOverride;
+
+ if (opacity < 1.0f)
+ opacityOverride = opacity;
+
+ return Disposable.Create(() =>
+ {
+ opacityOverride = tmp;
+ });
}
///
@@ -238,44 +238,84 @@ namespace Perspex.Cairo.Media
/// A disposable used to undo the transformation.
public IDisposable PushTransform(Matrix matrix)
{
- this.context.Transform(matrix.ToCairo());
+ _context.Transform(matrix.ToCairo());
return Disposable.Create(() =>
{
- this.context.Transform(matrix.Invert().ToCairo());
+ _context.Transform(matrix.Invert().ToCairo());
});
}
+
+ private double opacityOverride = 1.0f;
- private void SetBrush(Brush brush, Size destinationSize)
+ private IDisposable SetBrush(Brush brush, Size destinationSize)
{
+ _context.Save ();
+
var solid = brush as SolidColorBrush;
var linearGradientBrush = brush as LinearGradientBrush;
+ var radialGradientBrush = brush as RadialGradientBrush;
+ var imageBrush = brush as ImageBrush;
+ var visualBrush = brush as VisualBrush;
+ BrushImpl impl = null;
- if (solid != null)
+ if (solid != null)
+ {
+ impl = new SolidColorBrushImpl(solid, opacityOverride);
+ }
+ else if (linearGradientBrush != null)
+ {
+ impl = new LinearGradientBrushImpl(linearGradientBrush, destinationSize);
+ }
+ else if (radialGradientBrush != null)
{
- this.context.SetSourceRGBA(
- solid.Color.R / 255.0,
- solid.Color.G / 255.0,
- solid.Color.B / 255.0,
- solid.Color.A / 255.0);
+ impl = new RadialGradientBrushImpl(radialGradientBrush, destinationSize);
}
- else if (linearGradientBrush != null)
- {
- Cairo.LinearGradient g = new Cairo.LinearGradient(linearGradientBrush.StartPoint.X * destinationSize.Width, linearGradientBrush.StartPoint.Y * destinationSize.Height, linearGradientBrush.EndPoint.X * destinationSize.Width, linearGradientBrush.EndPoint.Y * destinationSize.Height);
-
- foreach (var s in linearGradientBrush.GradientStops)
- g.AddColorStopRgb(s.Offset, new Cairo.Color(s.Color.R, s.Color.G, s.Color.B, s.Color.A));
-
- g.Extend = Cairo.Extend.Pad;
+ else if (imageBrush != null)
+ {
+ impl = new ImageBrushImpl(imageBrush, destinationSize);
+ }
+ else if (visualBrush != null)
+ {
+ impl = new VisualBrushImpl(visualBrush, destinationSize);
+ }
+ else
+ {
+ impl = new SolidColorBrushImpl(null, opacityOverride);
+ }
- this.context.SetSource(g);
- }
+ _context.SetSource(impl.PlatformBrush);
+ return Disposable.Create(() =>
+ {
+ impl.Dispose();
+ _context.Restore();
+ });
}
- private void SetPen(Pen pen, Size destinationSize)
+ private IDisposable SetPen(Pen pen, Size destinationSize)
{
- this.SetBrush(pen.Brush, destinationSize);
- this.context.LineWidth = pen.Thickness;
+ if (pen.DashStyle != null)
+ {
+ if (pen.DashStyle.Dashes != null && pen.DashStyle.Dashes.Count > 0)
+ {
+ var cray = pen.DashStyle.Dashes.ToArray();
+ _context.SetDash(cray, pen.DashStyle.Offset);
+ }
+ }
+
+ _context.LineWidth = pen.Thickness;
+ _context.MiterLimit = pen.MiterLimit;
+
+ // Line caps and joins are currently broken on Cairo. I've defaulted them to sensible defaults for now.
+ // Cairo does not have StartLineCap, EndLineCap, and DashCap properties, whereas Direct2D does.
+ // TODO: Figure out a solution for this.
+ _context.LineJoin = Cairo.LineJoin.Miter;
+ _context.LineCap = Cairo.LineCap.Butt;
+
+ if (pen.Brush == null)
+ return Disposable.Empty;
+
+ return SetBrush(pen.Brush, destinationSize);
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs b/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs
index c43dc10fca..45987973b5 100644
--- a/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs
+++ b/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs
@@ -1,21 +1,23 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Perspex.Media;
+using Perspex.Platform;
+using Splat;
namespace Perspex.Cairo.Media
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Perspex.Media;
- using Perspex.Platform;
- using Splat;
-
public class FormattedTextImpl : IFormattedTextImpl
{
+ private Size _size;
+ private string _text;
+
public FormattedTextImpl(
+ Pango.Context context,
string text,
string fontFamily,
double fontSize,
@@ -23,44 +25,46 @@ namespace Perspex.Cairo.Media
TextAlignment textAlignment,
FontWeight fontWeight)
{
- var context = Locator.Current.GetService();
- this.Layout = new Pango.Layout(context);
- this.Layout.SetText(text);
- this.Layout.FontDescription = new Pango.FontDescription
+ Contract.Requires(context != null);
+
+ Layout = new Pango.Layout(context);
+ _text = text;
+ Layout.SetText(text);
+ Layout.FontDescription = new Pango.FontDescription
{
Family = fontFamily,
- Size = Pango.Units.FromDouble(fontSize * 0.73),
+ Size = Pango.Units.FromDouble(fontSize),
Style = (Pango.Style)fontStyle,
Weight = fontWeight.ToCairo()
};
-
- this.Layout.Alignment = textAlignment.ToCairo();
+
+ Layout.Alignment = textAlignment.ToCairo();
+ Layout.Attributes = new Pango.AttrList();
}
- private Size size;
public Size Constraint
{
get
{
- return size;
+ return _size;
}
set
{
- this.size = value;
- this.Layout.Width = Pango.Units.FromDouble(value.Width);
+ _size = value;
+ Layout.Width = double.IsPositiveInfinity(value.Width) ?
+ -1 : Pango.Units.FromDouble(value.Width);
}
}
public Pango.Layout Layout
{
get;
- private set;
}
public void Dispose()
{
- this.Layout.Dispose();
+ Layout.Dispose();
}
public IEnumerable GetLines()
@@ -73,12 +77,14 @@ namespace Perspex.Cairo.Media
int textPosition;
int trailing;
- var isInside = this.Layout.XyToIndex(
+ var isInside = Layout.XyToIndex(
Pango.Units.FromDouble(point.X),
Pango.Units.FromDouble(point.Y),
out textPosition,
out trailing);
+ textPosition = PangoIndexToTextIndex(textPosition);
+
return new TextHitTestResult
{
IsInside = isInside,
@@ -87,20 +93,30 @@ namespace Perspex.Cairo.Media
};
}
+ int PangoIndexToTextIndex(int pangoIndex)
+ {
+ return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(_text), 0, Math.Min(pangoIndex, _text.Length)).Length;
+ }
+
public Rect HitTestTextPosition(int index)
{
- return this.Layout.IndexToPos(index).ToPerspex();
+ return Layout.IndexToPos(TextIndexToPangoIndex(index)).ToPerspex();
+ }
+
+ int TextIndexToPangoIndex(int textIndex)
+ {
+ return Encoding.UTF8.GetByteCount(textIndex < _text.Length ? _text.Remove(textIndex) : _text);
}
public IEnumerable HitTestTextRange(int index, int length)
{
var ranges = new List();
-
+
for (var i = 0; i < length; i++)
{
- ranges.Add(this.HitTestTextPosition(index+i));
+ ranges.Add(HitTestTextPosition(index + i));
}
-
+
return ranges;
}
@@ -108,14 +124,26 @@ namespace Perspex.Cairo.Media
{
int width;
int height;
- this.Layout.GetPixelSize(out width, out height);
-
+ Layout.GetPixelSize(out width, out height);
+
return new Size(width, height);
}
public void SetForegroundBrush(Brush brush, int startIndex, int count)
{
- // TODO: Implement.
+ var scb = brush as SolidColorBrush;
+ if (scb != null)
+ {
+
+ var color = new Pango.Color();
+ color.Parse(string.Format("#{0}", scb.Color.ToString().Substring(3)));
+
+ var brushAttr = new Pango.AttrForeground(color);
+ brushAttr.StartIndex = (uint)TextIndexToPangoIndex(startIndex);
+ brushAttr.EndIndex = (uint)TextIndexToPangoIndex(startIndex + count);
+
+ Layout.Attributes.Insert(brushAttr);
+ }
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs
new file mode 100644
index 0000000000..d6c781619c
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs
@@ -0,0 +1,14 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo.Media
+{
+ public class ImageBrushImpl : BrushImpl
+ {
+ public ImageBrushImpl(Perspex.Media.ImageBrush brush, Size destinationSize)
+ {
+ this.PlatformBrush = TileBrushes.CreateImageBrush(brush, destinationSize);
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Media/Imaging/BitmapImpl.cs b/src/Gtk/Perspex.Cairo/Media/Imaging/BitmapImpl.cs
index 34961e7795..4abecba6c6 100644
--- a/src/Gtk/Perspex.Cairo/Media/Imaging/BitmapImpl.cs
+++ b/src/Gtk/Perspex.Cairo/Media/Imaging/BitmapImpl.cs
@@ -1,41 +1,33 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Platform;
namespace Perspex.Cairo.Media.Imaging
{
- using System;
- using Perspex.Platform;
using Cairo = global::Cairo;
public class BitmapImpl : IBitmapImpl
{
- public BitmapImpl(Cairo.ImageSurface surface)
+ public BitmapImpl(Gdk.Pixbuf pixbuf)
{
- this.Surface = surface;
+ Surface = pixbuf;
}
- public int PixelWidth
- {
- get { return this.Surface.Width; }
- }
+ public int PixelWidth => Surface.Width;
- public int PixelHeight
- {
- get { return this.Surface.Height; }
- }
+ public int PixelHeight => Surface.Height;
- public Cairo.ImageSurface Surface
+ public Gdk.Pixbuf Surface
{
get;
- private set;
}
public void Save(string fileName)
{
- this.Surface.WriteToPng(fileName);
+ // TODO: Test
+ Surface.Save(fileName, "png");
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs b/src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
index 68404cbf03..db35a22775 100644
--- a/src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
+++ b/src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
@@ -1,32 +1,44 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Platform;
namespace Perspex.Cairo.Media.Imaging
{
- using System;
- using Perspex.Platform;
using Cairo = global::Cairo;
- public class RenderTargetBitmapImpl : BitmapImpl, IRenderTargetBitmapImpl
+ public class RenderTargetBitmapImpl : IRenderTargetBitmapImpl
{
- public RenderTargetBitmapImpl(
- Cairo.ImageSurface surface)
- : base(surface)
+ public RenderTargetBitmapImpl(Cairo.ImageSurface surface)
{
+ Surface = surface;
+ renderer = new Renderer(Surface);
}
+ public int PixelWidth => Surface.Width;
+
+ public int PixelHeight => Surface.Height;
+
public void Dispose()
{
- this.Surface.Dispose();
+ renderer.Dispose();
}
+ public Cairo.ImageSurface Surface
+ {
+ get;
+ }
+
+ private Renderer renderer;
public void Render(IVisual visual)
{
- Renderer renderer = new Renderer(this.Surface);
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"));
}
+
+ public void Save(string fileName)
+ {
+ Surface.WriteToPng(fileName);
+ }
}
}
\ No newline at end of file
diff --git a/src/Gtk/Perspex.Cairo/Media/LinearGradientBrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/LinearGradientBrushImpl.cs
new file mode 100644
index 0000000000..f1502275c7
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/LinearGradientBrushImpl.cs
@@ -0,0 +1,22 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo
+{
+ public class LinearGradientBrushImpl : BrushImpl
+ {
+ public LinearGradientBrushImpl(Perspex.Media.LinearGradientBrush brush, Size destinationSize)
+ {
+ var start = brush.StartPoint.ToPixels(destinationSize);
+ var end = brush.EndPoint.ToPixels(destinationSize);
+
+ this.PlatformBrush = new LinearGradient(start.X, start.Y, end.X, end.Y);
+
+ foreach (var stop in brush.GradientStops)
+ ((LinearGradient)this.PlatformBrush).AddColorStop(stop.Offset, stop.Color.ToCairo());
+
+ ((LinearGradient)this.PlatformBrush).Extend = Extend.Pad;
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Media/RadialGradientBrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/RadialGradientBrushImpl.cs
new file mode 100644
index 0000000000..a345f1869d
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/RadialGradientBrushImpl.cs
@@ -0,0 +1,25 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo
+{
+ public class RadialGradientBrushImpl : BrushImpl
+ {
+ public RadialGradientBrushImpl(Perspex.Media.RadialGradientBrush brush, Size destinationSize)
+ {
+ var center = brush.Center.ToPixels(destinationSize);
+ var gradientOrigin = brush.GradientOrigin.ToPixels(destinationSize);
+ var radius = brush.Radius;
+
+ this.PlatformBrush = new RadialGradient(center.X, center.Y, radius, gradientOrigin.X, gradientOrigin.Y, radius);
+
+ foreach (var stop in brush.GradientStops)
+ {
+ ((LinearGradient)this.PlatformBrush).AddColorStop(stop.Offset, stop.Color.ToCairo());
+ }
+
+ ((LinearGradient)this.PlatformBrush).Extend = Extend.Pad;
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Media/SolidColorBrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/SolidColorBrushImpl.cs
new file mode 100644
index 0000000000..10e63f0382
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/SolidColorBrushImpl.cs
@@ -0,0 +1,22 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo
+{
+ public class SolidColorBrushImpl : BrushImpl
+ {
+ public SolidColorBrushImpl(Perspex.Media.SolidColorBrush brush, double opacityOverride = 1.0f)
+ {
+ var color = brush?.Color.ToCairo() ?? new Color();
+
+ if (brush != null)
+ color.A = Math.Min(brush.Opacity, color.A);
+
+ if (opacityOverride < 1.0f)
+ color.A = Math.Min(opacityOverride, color.A);
+
+ this.PlatformBrush = new SolidPattern(color);
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs b/src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
index ff9dacca08..a49ac7ef90 100644
--- a/src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
+++ b/src/Gtk/Perspex.Cairo/Media/StreamGeometryContextImpl.cs
@@ -1,25 +1,28 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2013 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using Perspex.Media;
+using Perspex.Platform;
namespace Perspex.Cairo.Media
{
- using Perspex.Media;
- using Perspex.Platform;
- using System;
- using System.Collections.Generic;
using Cairo = global::Cairo;
public class StreamGeometryContextImpl : IStreamGeometryContextImpl
{
- private StreamGeometryImpl impl;
- public StreamGeometryContextImpl(StreamGeometryImpl imp)
+ public StreamGeometryContextImpl(Cairo.Path path = null)
{
- this.impl = imp;
- this.surf = new Cairo.ImageSurface(Cairo.Format.Argb32, 0, 0);
- this.context = new Cairo.Context(this.surf);
+
+ _surf = new Cairo.ImageSurface (Cairo.Format.Argb32, 0, 0);
+ _context = new Cairo.Context (_surf);
+ this.Path = path;
+
+ if (this.Path != null)
+ {
+ _context.AppendPath(this.Path);
+ }
}
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection)
@@ -28,62 +31,43 @@ namespace Perspex.Cairo.Media
public void BeginFigure(Point startPoint, bool isFilled)
{
- this.impl.Operations.Enqueue(new BeginOp { Point = startPoint, IsFilled = isFilled });
+ if (this.Path == null)
+ _context.MoveTo(startPoint.ToCairo());
}
public void BezierTo(Point point1, Point point2, Point point3)
{
- this.impl.Operations.Enqueue(new CurveToOp { Point = point1, Point2 = point2, Point3 = point3 });
+ if (this.Path == null)
+ _context.CurveTo(point1.ToCairo(), point2.ToCairo(), point3.ToCairo());
}
public void LineTo(Point point)
{
- this.impl.Operations.Enqueue(new LineToOp { Point = point });
+ if (this.Path == null)
+ _context.LineTo(point.ToCairo());
}
- private Cairo.Context context;
- private Cairo.ImageSurface surf;
+ private readonly Cairo.Context _context;
+ private readonly Cairo.ImageSurface _surf;
+ public Cairo.Path Path { get; private set; }
+ public Rect Bounds { get; private set; }
public void EndFigure(bool isClosed)
{
- this.impl.Operations.Enqueue(new EndOp { IsClosed = isClosed });
-
- var clone = new Queue(this.impl.Operations);
-
- while (clone.Count > 0)
- {
- var current = clone.Dequeue();
-
- if (current is BeginOp)
- {
- var bo = current as BeginOp;
- context.MoveTo(bo.Point.ToCairo());
- }
- else if (current is LineToOp)
- {
- var lto = current as LineToOp;
- context.LineTo(lto.Point.ToCairo());
- }
- else if (current is EndOp)
- {
- if (((EndOp)current).IsClosed)
- context.ClosePath();
- }
- else if (current is CurveToOp)
- {
- var cto = current as CurveToOp;
- context.CurveTo(cto.Point.ToCairo(), cto.Point2.ToCairo(), cto.Point3.ToCairo());
- }
- }
+ if (this.Path == null)
+ {
+ if (isClosed)
+ _context.ClosePath ();
- var extents = context.StrokeExtents();
- this.impl.Bounds = new Rect(extents.X, extents.Y, extents.Width, extents.Height);
+ Path = _context.CopyPath ();
+ Bounds = _context.FillExtents ().ToPerspex ();
+ }
}
public void Dispose()
{
- context.Dispose();
- surf.Dispose();
+ _context.Dispose ();
+ _surf.Dispose ();
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs b/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs
index cf423dbc17..7e7f520f02 100644
--- a/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs
+++ b/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs
@@ -1,107 +1,70 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Media;
+using Perspex.Platform;
+using Splat;
+using System.Collections.Generic;
namespace Perspex.Cairo.Media
{
- using System;
- using Perspex.Media;
- using Perspex.Platform;
using Cairo = global::Cairo;
- using Splat;
- using System.Collections.Generic;
-
- public enum CairoGeometryType
- {
- Begin,
- ArcTo,
- LineTo,
- End
- }
-
- public class BeginOp : GeometryOp
- {
- public Point Point { get; set; }
- public bool IsFilled { get; set; }
- }
-
- public class EndOp : GeometryOp
- {
- public bool IsClosed { get; set; }
- }
-
- public class LineToOp : GeometryOp
- {
- public Point Point { get; set; }
- }
-
- public class CurveToOp : GeometryOp
- {
- public Point Point { get; set; }
- public Point Point2 { get; set; }
- public Point Point3 { get; set; }
- }
-
- public abstract class GeometryOp
- {
- }
public class StreamGeometryImpl : IStreamGeometryImpl
{
public StreamGeometryImpl()
{
- this.Operations = new Queue();
+ _impl = new StreamGeometryContextImpl(null);
}
- public StreamGeometryImpl(Queue ops)
+ public StreamGeometryImpl(StreamGeometryContextImpl impl)
{
- this.Operations = ops;
- }
-
- public Queue Operations
- {
- get;
- private set;
+ _impl = impl;
}
public Rect Bounds
{
- get;
- set;
- }
+ get { return _impl.Bounds; }
+ }
- // TODO: Implement
- private Matrix transform = Matrix.Identity;
+ public Cairo.Path Path
+ {
+ get { return _impl.Path; }
+ }
+
+ private readonly StreamGeometryContextImpl _impl;
+
+ private Matrix _transform = Matrix.Identity;
public Matrix Transform
{
- get { return this.transform; }
+ get { return _transform; }
set
{
- if (value != this.Transform)
+ if (value != Transform)
{
- if (!value.IsIdentity)
- {
- this.transform = value;
- }
+ if (!value.IsIdentity)
+ {
+ _transform = value;
+ }
}
}
}
public IStreamGeometryImpl Clone()
- {
- return new StreamGeometryImpl(this.Operations);
+ {
+ return new StreamGeometryImpl(_impl);
}
public Rect GetRenderBounds(double strokeThickness)
{
- return this.Bounds;
+ // TODO: Calculate properly.
+ return Bounds.Inflate(strokeThickness);
}
public IStreamGeometryContextImpl Open()
{
- return new StreamGeometryContextImpl(this);
+ return _impl;
}
}
}
diff --git a/src/Gtk/Perspex.Cairo/Media/TileBrushes.cs b/src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
new file mode 100644
index 0000000000..e08565785a
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
@@ -0,0 +1,224 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Cairo;
+using Perspex.Cairo.Media.Imaging;
+using Perspex.Layout;
+using Perspex.Media;
+using Perspex.Platform;
+
+namespace Perspex.Cairo.Media
+{
+ internal static class TileBrushes
+ {
+ public static SurfacePattern CreateImageBrush(ImageBrush brush, Size targetSize)
+ {
+ if (brush.Source == null)
+ {
+ return null;
+ }
+
+ // TODO: This is directly ported from Direct2D and could probably be made more
+ // efficient on cairo by taking advantage of the fact that cairo has Extend.None.
+ var image = ((BitmapImpl)brush.Source.PlatformImpl).Surface;
+ var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight);
+ var tileMode = brush.TileMode;
+ var sourceRect = brush.SourceRect.ToPixels(imageSize);
+ var destinationRect = brush.DestinationRect.ToPixels(targetSize);
+ var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
+ var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
+ var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
+
+ var intermediate = new ImageSurface (Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height);
+ using (var context = new Context(intermediate))
+ {
+ Rect drawRect;
+ var transform = CalculateIntermediateTransform(
+ tileMode,
+ sourceRect,
+ destinationRect,
+ scale,
+ translate,
+ out drawRect);
+ context.Rectangle(drawRect.ToCairo());
+ context.Clip();
+ context.Transform(transform.ToCairo());
+ Gdk.CairoHelper.SetSourcePixbuf(context, image, 0, 0);
+ context.Rectangle(0, 0, imageSize.Width, imageSize.Height);
+ context.Fill();
+
+ var result = new SurfacePattern(intermediate);
+
+ if ((brush.TileMode & TileMode.FlipXY) != 0)
+ {
+ // TODO: Currently always FlipXY as that's all cairo supports natively.
+ // Support separate FlipX and FlipY by drawing flipped images to intermediate
+ // surface.
+ result.Extend = Extend.Reflect;
+ }
+ else
+ {
+ result.Extend = Extend.Repeat;
+ }
+
+ if (brush.TileMode != TileMode.None)
+ {
+ var matrix = result.Matrix;
+ matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
+ result.Matrix = matrix;
+ }
+
+ return result;
+ }
+ }
+
+ public static SurfacePattern CreateVisualBrush(VisualBrush brush, Size targetSize)
+ {
+ var visual = brush.Visual;
+
+ if (visual == null)
+ {
+ return null;
+ }
+
+ var layoutable = visual as ILayoutable;
+
+ if (layoutable?.IsArrangeValid == false)
+ {
+ layoutable.Measure(Size.Infinity);
+ layoutable.Arrange(new Rect(layoutable.DesiredSize));
+ }
+
+ // TODO: This is directly ported from Direct2D and could probably be made more
+ // efficient on cairo by taking advantage of the fact that cairo has Extend.None.
+ var tileMode = brush.TileMode;
+ var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size);
+ var destinationRect = brush.DestinationRect.ToPixels(targetSize);
+ var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
+ var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
+ var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
+
+ using (var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height))
+ using (var context = new Context(intermediate))
+ {
+ Rect drawRect;
+ var transform = CalculateIntermediateTransform(
+ tileMode,
+ sourceRect,
+ destinationRect,
+ scale,
+ translate,
+ out drawRect);
+ var renderer = new Renderer(intermediate);
+
+ context.Rectangle(drawRect.ToCairo());
+ context.Clip();
+ context.Transform(transform.ToCairo());
+ renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"), transform, drawRect);
+
+ var result = new SurfacePattern(intermediate);
+
+ if ((brush.TileMode & TileMode.FlipXY) != 0)
+ {
+ // TODO: Currently always FlipXY as that's all cairo supports natively.
+ // Support separate FlipX and FlipY by drawing flipped images to intermediate
+ // surface.
+ result.Extend = Extend.Reflect;
+ }
+ else
+ {
+ result.Extend = Extend.Repeat;
+ }
+
+ if (brush.TileMode != TileMode.None)
+ {
+ var matrix = result.Matrix;
+ matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
+ result.Matrix = matrix;
+ }
+
+ return result;
+ }
+ }
+
+ ///
+ /// Calculates a translate based on a , a source and destination
+ /// rectangle and a scale.
+ ///
+ /// The brush.
+ /// The source rectangle.
+ /// The destination rectangle.
+ /// The scale factor.
+ /// A vector with the X and Y translate.
+ private static Vector CalculateTranslate(
+ TileBrush brush,
+ Rect sourceRect,
+ Rect destinationRect,
+ Vector scale)
+ {
+ var x = 0.0;
+ var y = 0.0;
+ var size = sourceRect.Size * scale;
+
+ switch (brush.AlignmentX)
+ {
+ case AlignmentX.Center:
+ x += (destinationRect.Width - size.Width) / 2;
+ break;
+ case AlignmentX.Right:
+ x += destinationRect.Width - size.Width;
+ break;
+ }
+
+ switch (brush.AlignmentY)
+ {
+ case AlignmentY.Center:
+ y += (destinationRect.Height - size.Height) / 2;
+ break;
+ case AlignmentY.Bottom:
+ y += destinationRect.Height - size.Height;
+ break;
+ }
+
+ return new Vector(x, y);
+ }
+
+ private static Size CalculateIntermediateSize(
+ TileMode tileMode,
+ Size targetSize,
+ Size destinationSize)
+ {
+ var result = tileMode == TileMode.None ? targetSize : destinationSize;
+ return result;
+ }
+
+ private static Matrix CalculateIntermediateTransform(
+ TileMode tileMode,
+ Rect sourceRect,
+ Rect destinationRect,
+ Vector scale,
+ Vector translate,
+ out Rect drawRect)
+ {
+ var transform = Matrix.CreateTranslation(-sourceRect.Position) *
+ Matrix.CreateScale(scale) *
+ Matrix.CreateTranslation(translate);
+ Rect dr;
+
+ if (tileMode == TileMode.None)
+ {
+ dr = destinationRect;
+ transform *= Matrix.CreateTranslation(destinationRect.Position);
+ }
+ else
+ {
+ dr = new Rect(destinationRect.Size);
+ }
+
+ drawRect = dr;
+
+ return transform;
+ }
+ }
+}
diff --git a/src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs b/src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs
new file mode 100644
index 0000000000..634b2b38a5
--- /dev/null
+++ b/src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs
@@ -0,0 +1,14 @@
+using System;
+using global::Cairo;
+
+namespace Perspex.Cairo.Media
+{
+ public class VisualBrushImpl : BrushImpl
+ {
+ public VisualBrushImpl(Perspex.Media.VisualBrush brush, Size destinationSize)
+ {
+ this.PlatformBrush = TileBrushes.CreateVisualBrush(brush, destinationSize);
+ }
+ }
+}
+
diff --git a/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj b/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
index f612517ebd..6e4155d610 100644
--- a/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
+++ b/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
@@ -32,22 +32,10 @@
4
-
- gtk-sharp-2.0
-
-
- glib-sharp-2.0
-
-
- gtk-sharp-2.0
-
-
- gtk-sharp-2.0
-
-
- ..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
- True
-
+
+
+
+
@@ -62,8 +50,9 @@
..\..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll
-
- gtk-sharp-2.0
+
+
+ ..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
@@ -72,31 +61,43 @@
+
+
+
+
+
+
+
- {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+ {D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
{B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
+
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
+ Perspex.Layout
+
{EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/IVisitor.cs b/src/NGenerics/Patterns/Visitor/IVisitor.cs
deleted file mode 100644
index d9460e51a9..0000000000
--- a/src/NGenerics/Patterns/Visitor/IVisitor.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// Provides an interface for visitors.
- ///
- /// The type of objects to be visited.
- public interface IVisitor
- {
- ///
- /// Gets a value indicating whether this instance is done performing it's work..
- ///
- /// true if this instance is done; otherwise, false.
- bool HasCompleted { get; }
-
- ///
- /// Visits the specified object.
- ///
- /// The object to visit.
- void Visit(T obj);
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/InOrderVisitor.cs b/src/NGenerics/Patterns/Visitor/InOrderVisitor.cs
deleted file mode 100644
index 12ba98e55e..0000000000
--- a/src/NGenerics/Patterns/Visitor/InOrderVisitor.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// An in order implementation of the class.
- ///
- /// The type of objects to be visited.
- public sealed class InOrderVisitor : OrderedVisitor
- {
- #region Construction
-
- /// The visitor.
- public InOrderVisitor(IVisitor visitor) : base(visitor) { }
-
- #endregion
-
- #region OrderedVisitor Members
-
- ///
- /// Visits the object in post order.
- ///
- /// The obj.
- public override void VisitPostOrder(T obj)
- {
- // Do nothing.
- }
-
- ///
- /// Visits the object in pre order.
- ///
- /// The obj.
- public override void VisitPreOrder(T obj)
- {
- // Do nothing.
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/KeyTrackingVisitor.cs b/src/NGenerics/Patterns/Visitor/KeyTrackingVisitor.cs
deleted file mode 100644
index d03f935fe3..0000000000
--- a/src/NGenerics/Patterns/Visitor/KeyTrackingVisitor.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-using System.Collections.Generic;
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// A visitor that tracks (stores) keys from KeyValuePAirs in the order they were visited.
- ///
- /// The type of the keys for the items to be visited.
- /// The type of the values for the items to be visited.
- public sealed class KeyTrackingVisitor : IVisitor>
- {
- #region Globals
-
- private readonly List tracks;
-
- #endregion
-
- #region Construction
-
- ///
- public KeyTrackingVisitor()
- {
- tracks = new List();
- }
-
- #endregion
-
- #region Public Members
-
- ///
- /// Gets the tracking list.
- ///
- /// The tracking list.
- public IList TrackingList
- {
- get
- {
- return tracks;
- }
- }
-
- #endregion
-
- #region IVisitor> Members
-
-
- ///
- public void Visit(KeyValuePair obj)
- {
- tracks.Add(obj.Key);
- }
-
- ///
- public bool HasCompleted
- {
- get
- {
- return false;
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/OrderedVisitor.cs b/src/NGenerics/Patterns/Visitor/OrderedVisitor.cs
deleted file mode 100644
index 881c4bfda1..0000000000
--- a/src/NGenerics/Patterns/Visitor/OrderedVisitor.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-using System;
-using System.Diagnostics.CodeAnalysis;
-using NGenerics.Util;
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// A visitor that visits objects in order (PreOrder, PostOrder, or InOrder).
- /// Used primarily as a base class for Visitors specializing in a specific order type.
- ///
- /// The type of objects to be visited.
- public class OrderedVisitor : IVisitor
- {
- #region Globals
-
- private readonly IVisitor visitorToUse;
-
- #endregion
-
- #region Construction
-
- /// The visitor to use when visiting the object.
- /// is a null reference (Nothing in Visual Basic).
- public OrderedVisitor(IVisitor visitorToUse)
- {
- Guard.ArgumentNotNull(visitorToUse, "visitorToUse");
-
- this.visitorToUse = visitorToUse;
- }
-
- #endregion
-
- #region IOrderedVisitor Members
-
- ///
- /// Determines whether this visitor is done.
- ///
- ///
- ///
- /// true if this visitor is done; otherwise, false.
- ///
- public bool HasCompleted
- {
- get
- {
- return visitorToUse.HasCompleted;
- }
- }
-
- ///
- /// Visits the object in pre order.
- ///
- /// The obj.
- [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "PreOrder")]
- public virtual void VisitPreOrder(T obj)
- {
- visitorToUse.Visit(obj);
- }
-
- ///
- /// Visits the object in post order.
- ///
- /// The obj.
- public virtual void VisitPostOrder(T obj)
- {
- visitorToUse.Visit(obj);
- }
-
- ///
- /// Visits the object in order.
- ///
- /// The obj.
- public virtual void VisitInOrder(T obj)
- {
- visitorToUse.Visit(obj);
- }
- ///
- public void Visit(T obj)
- {
- visitorToUse.Visit(obj);
- }
-
- #endregion
-
- #region Public Members
-
- ///
- /// Gets the visitor to use.
- ///
- /// The visitor to use.
- public IVisitor VisitorToUse
- {
- get
- {
- return visitorToUse;
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/TrackingVisitor.cs b/src/NGenerics/Patterns/Visitor/TrackingVisitor.cs
deleted file mode 100644
index 17d4c67fa4..0000000000
--- a/src/NGenerics/Patterns/Visitor/TrackingVisitor.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-using System.Collections.Generic;
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// A visitor that tracks (stores) objects in the order they were visited.
- /// Handy for demonstrating and testing different ordered visits implementations on
- /// data structures.
- ///
- /// The type of objects to be visited.
- public sealed class TrackingVisitor : IVisitor
- {
- #region Globals
-
- private readonly List tracks;
-
- #endregion
-
- #region Construction
-
-
- ///
- public TrackingVisitor()
- {
- tracks = new List();
- }
-
- #endregion
-
- #region IVisitor Members
- ///
- public void Visit(T obj)
- {
- tracks.Add(obj);
- }
-
- ///
- public bool HasCompleted {
- get
- {
- return false;
- }
- }
-
- #endregion
-
- #region Public Members
-
- ///
- /// Gets the tracking list.
- ///
- /// The tracking list.
- public IList TrackingList
- {
- get
- {
- return tracks;
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Patterns/Visitor/ValueTrackingVisitor.cs b/src/NGenerics/Patterns/Visitor/ValueTrackingVisitor.cs
deleted file mode 100644
index 01d79e6617..0000000000
--- a/src/NGenerics/Patterns/Visitor/ValueTrackingVisitor.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-using System.Collections.Generic;
-
-namespace NGenerics.Patterns.Visitor
-{
- ///
- /// A visitor that tracks (stores) keys from KeyValuePairs in the order they were visited.
- ///
- /// The type of key of the KeyValuePair.
- /// The type of value of the KeyValuePair.
- public sealed class ValueTrackingVisitor : IVisitor>
- {
- #region Globals
-
- private readonly List tracks;
-
- #endregion
-
- #region Construction
-
-
- ///
- public ValueTrackingVisitor()
- {
- tracks = new List();
- }
-
- #endregion
-
- #region Public Members
-
- ///
- /// Gets the tracking list.
- ///
- /// The tracking list.
- public IList TrackingList
- {
- get
- {
- return tracks;
- }
- }
-
- #endregion
-
- #region IVisitor> Members
-
-
- ///
- public void Visit(KeyValuePair obj)
- {
- tracks.Add(obj.Value);
- }
-
- ///
- public bool HasCompleted
- {
- get
- {
- return false;
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/NGenerics/Util/Guard.cs b/src/NGenerics/Util/Guard.cs
deleted file mode 100644
index 89f70a7cba..0000000000
--- a/src/NGenerics/Util/Guard.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- Copyright 2007-2013 The NGenerics Team
- (https://github.com/ngenerics/ngenerics/wiki/Team)
-
- This program is licensed under the GNU Lesser General Public License (LGPL). You should
- have received a copy of the license along with the source code. If not, an online copy
- of the license can be found at http://www.gnu.org/copyleft/lesser.html.
-*/
-
-
-using System;
-
-namespace NGenerics.Util
-{
- ///
- /// Performs common argument validation.
- ///
- public static class Guard
- {
- #region Methods
-
- ///
- /// Checks a string argument to ensure it isn't null or empty.
- ///
- /// The argument value to check.
- /// The name of the argument.
- /// is a null reference.
- /// is .
- public static void ArgumentNotNullOrEmptyString(string argumentValue, string argumentName)
- {
- ArgumentNotNull(argumentValue, argumentName);
-
- if (argumentValue.Length == 0)
- {
- throw new ArgumentException("String cannot be empty.", argumentName);
- }
- }
-
-
- ///
- /// Checks an argument to ensure it isn't null.
- ///
- /// The argument value to check.
- /// The name of the argument.
- /// is a null reference.
- public static void ArgumentNotNull(object argumentValue, string argumentName)
- {
- if (argumentValue == null)
- {
- throw new ArgumentNullException(argumentName);
- }
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/Perspex.Animation/Animatable.cs b/src/Perspex.Animation/Animatable.cs
index bff50a2e46..33c7f611ad 100644
--- a/src/Perspex.Animation/Animatable.cs
+++ b/src/Perspex.Animation/Animatable.cs
@@ -1,13 +1,10 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Linq;
namespace Perspex.Animation
{
- using System.Linq;
-
///
/// Base class for control which can have property transitions.
///
@@ -16,7 +13,7 @@ namespace Perspex.Animation
///
/// The property transitions for the control.
///
- private PropertyTransitions propertyTransitions;
+ private PropertyTransitions _propertyTransitions;
///
/// Gets or sets the property transitions for the control.
@@ -28,17 +25,17 @@ namespace Perspex.Animation
{
get
{
- if (this.propertyTransitions == null)
+ if (_propertyTransitions == null)
{
- this.propertyTransitions = new PropertyTransitions();
+ _propertyTransitions = new PropertyTransitions();
}
- return this.propertyTransitions;
+ return _propertyTransitions;
}
set
{
- this.propertyTransitions = value;
+ _propertyTransitions = value;
}
}
@@ -49,9 +46,9 @@ namespace Perspex.Animation
/// The event args.
protected override void OnPropertyChanged(PerspexPropertyChangedEventArgs e)
{
- if (e.Priority != BindingPriority.Animation && this.propertyTransitions != null)
+ if (e.Priority != BindingPriority.Animation && _propertyTransitions != null)
{
- var match = this.propertyTransitions.FirstOrDefault(x => x.Property == e.Property);
+ var match = _propertyTransitions.FirstOrDefault(x => x.Property == e.Property);
if (match != null)
{
diff --git a/src/Perspex.Animation/Animate.cs b/src/Perspex.Animation/Animate.cs
index d3e2e76463..85db3e71b7 100644
--- a/src/Perspex.Animation/Animate.cs
+++ b/src/Perspex.Animation/Animate.cs
@@ -1,17 +1,14 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Reactive.Linq;
+using Perspex.Threading;
namespace Perspex.Animation
{
- using System;
- using System.Diagnostics;
- using System.Linq;
- using System.Reactive.Linq;
- using Perspex.Threading;
-
///
/// Utilities for creating animations.
///
@@ -48,9 +45,7 @@ namespace Perspex.Animation
///
public static Stopwatch Stopwatch
{
- get;
- private set;
- }
+ get; }
///
/// Gets the animation timer.
@@ -65,9 +60,7 @@ namespace Perspex.Animation
///
public static IObservable Timer
{
- get;
- private set;
- }
+ get; }
///
/// Gets a timer that fires every frame for the specified duration.
diff --git a/src/Perspex.Animation/Animation.cs b/src/Perspex.Animation/Animation.cs
index 1afd8c02b2..26e839e154 100644
--- a/src/Perspex.Animation/Animation.cs
+++ b/src/Perspex.Animation/Animation.cs
@@ -1,13 +1,10 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2015 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
namespace Perspex.Animation
{
- using System;
-
///
/// Tracks the progress of an animation.
///
@@ -16,12 +13,12 @@ namespace Perspex.Animation
///
/// The animation being tracked.
///
- private IObservable
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs b/tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..575bdbad2f
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/Properties/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Reflection;
+
+[assembly: AssemblyTitle("Perspex.Markup.Xaml.UnitTests")]
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs b/tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs
new file mode 100644
index 0000000000..1b15094af5
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/PropertyMountPointTest.cs
@@ -0,0 +1,18 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Markup.Xaml.DataBinding.ChangeTracking;
+using System;
+using Xunit;
+
+namespace Perspex.Xaml.Base.UnitTest
+{
+ public class PropertyMountPointTest
+ {
+ [Fact]
+ public void SourceAndPathAreNull()
+ {
+ Assert.Throws(() => new PropertyMountPoint(null, null));
+ }
+ }
+}
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs
new file mode 100644
index 0000000000..e3ec6d96a3
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level1.cs
@@ -0,0 +1,44 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public class Level1 : PropertyChangeNotifier
+ {
+ private Level2 _level2 = new Level2();
+ private DateTime _dateTime;
+ private string _text;
+
+ public Level2 Level2
+ {
+ get { return _level2; }
+ set
+ {
+ _level2 = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Text
+ {
+ get { return _text; }
+ set
+ {
+ _text = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public DateTime DateTime
+ {
+ get { return _dateTime; }
+ set
+ {
+ _dateTime = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs
new file mode 100644
index 0000000000..0862309a97
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level2.cs
@@ -0,0 +1,20 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public class Level2 : PropertyChangeNotifier
+ {
+ private Level3 _level3 = new Level3();
+
+ public Level3 Level3
+ {
+ get { return _level3; }
+ set
+ {
+ _level3 = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs
new file mode 100644
index 0000000000..c22e7c268c
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Level3.cs
@@ -0,0 +1,20 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public class Level3 : PropertyChangeNotifier
+ {
+ private int _property = 10;
+
+ public int Property
+ {
+ get { return _property; }
+ set
+ {
+ _property = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs
new file mode 100644
index 0000000000..2b479b2f73
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/LogInViewModel.cs
@@ -0,0 +1,32 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using ReactiveUI;
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public class LogInViewModel : ReactiveObject
+ {
+ private string _username;
+
+ public LogInViewModel()
+ {
+ OkCommand = ReactiveCommand.Create(
+ this.WhenAnyValue(
+ x => x.Username,
+ x => !string.IsNullOrWhiteSpace(x)));
+ }
+
+ public string Username
+ {
+ get { return _username; }
+ set { this.RaiseAndSetIfChanged(ref _username, value); }
+ }
+
+ public ReactiveCommand OkCommand
+ {
+ get;
+ private set;
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs
new file mode 100644
index 0000000000..39ea070789
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/MainWindowViewModel.cs
@@ -0,0 +1,41 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Xaml.Base.UnitTest.SampleModel;
+using ReactiveUI;
+
+namespace GitHubClient.ViewModels
+{
+ public class MainWindowViewModel : ReactiveObject
+ {
+ private object _content;
+
+ private LogInViewModel _login;
+
+ public MainWindowViewModel()
+ {
+ ShowLogin();
+ }
+
+ public object Content
+ {
+ get { return _content; }
+ set { this.RaiseAndSetIfChanged(ref _content, value); }
+ }
+
+ private void ShowLogin()
+ {
+ _login = new LogInViewModel();
+ _login.OkCommand.Subscribe(_ => ShowRepositories());
+ Content = _login;
+ }
+
+ private void ShowRepositories()
+ {
+ var vm = new UserRepositoriesViewModel();
+ var task = vm.Load(_login.Username);
+ Content = vm;
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs
new file mode 100644
index 0000000000..c9dcebac85
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/PropertyChangeNotifier.cs
@@ -0,0 +1,18 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public abstract class PropertyChangeNotifier : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs
new file mode 100644
index 0000000000..dde5243264
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/Repository.cs
@@ -0,0 +1,17 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace GitHubClient.ViewModels
+{
+ public class Repository
+ {
+ private readonly string _name;
+
+ public Repository(string name)
+ {
+ _name = name;
+ }
+
+ public string Name => _name;
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs
new file mode 100644
index 0000000000..4fce0e90b4
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SampleModel/UserRepositoriesViewModel.cs
@@ -0,0 +1,26 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using GitHubClient.ViewModels;
+using ReactiveUI;
+
+namespace Perspex.Xaml.Base.UnitTest.SampleModel
+{
+ public class UserRepositoriesViewModel : ReactiveObject
+ {
+ private IReadOnlyList _repositories;
+
+ public async Task Load(string username)
+ {
+ Repositories = await new Task>(() => new List { new Repository("Blah"), new Repository("Bleh") });
+ }
+
+ public IReadOnlyList Repositories
+ {
+ get { return _repositories; }
+ private set { this.RaiseAndSetIfChanged(ref _repositories, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs b/tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs
new file mode 100644
index 0000000000..60aaf4c586
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/SamplePerspexObject.cs
@@ -0,0 +1,28 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+
+namespace Perspex.Xaml.Base.UnitTest
+{
+ internal class SamplePerspexObject : PerspexObject
+ {
+ public static readonly PerspexProperty StringProperty =
+ PerspexProperty.Register("StrProp", string.Empty);
+
+ public static readonly PerspexProperty IntProperty =
+ PerspexProperty.Register("IntProp");
+
+ public int Int
+ {
+ get { return GetValue(IntProperty); }
+ set { SetValue(IntProperty, value); }
+ }
+
+ public string String
+ {
+ get { return GetValue(StringProperty); }
+ set { SetValue(StringProperty, value); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs b/tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs
new file mode 100644
index 0000000000..673369f641
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/TypeProviderMock.cs
@@ -0,0 +1,38 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using OmniXaml;
+using System;
+
+namespace Perspex.Xaml.Base.UnitTest
+{
+ internal class TypeProviderMock : ITypeProvider
+ {
+ private readonly string _typeName;
+ private readonly string _clrNamespace;
+ private readonly string _assemblyName;
+ private readonly Type _typeToReturn;
+
+ public TypeProviderMock(string typeName, string clrNamespace, string assemblyName, Type typeToReturn)
+ {
+ _typeName = typeName;
+ _clrNamespace = clrNamespace;
+ _assemblyName = assemblyName;
+ _typeToReturn = typeToReturn;
+ }
+
+ public TypeProviderMock()
+ {
+ }
+
+ public Type GetType(string typeName, string clrNamespace, string assemblyName)
+ {
+ if (_typeName == typeName && _clrNamespace == clrNamespace && _assemblyName == assemblyName)
+ {
+ return _typeToReturn;
+ }
+
+ throw new TypeNotFoundException("The Type cannot be found");
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs b/tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs
new file mode 100644
index 0000000000..4bdfe94e0e
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/ViewModelMock.cs
@@ -0,0 +1,41 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace Perspex.Xaml.Base.UnitTest
+{
+ internal class ViewModelMock : INotifyPropertyChanged
+ {
+ private string _str;
+ private int _intProp;
+
+ public int IntProp
+ {
+ get { return _intProp; }
+ set
+ {
+ _intProp = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string StrProp
+ {
+ get { return _str; }
+ set
+ {
+ _str = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs b/tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs
new file mode 100644
index 0000000000..d7ee56245f
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/XamlBindingTest.cs
@@ -0,0 +1,21 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Moq;
+using Perspex.Markup.Xaml.DataBinding;
+using OmniXaml.TypeConversion;
+using Xunit;
+
+namespace Perspex.Xaml.Base.UnitTest
+{
+ public class XamlBindingTest
+ {
+ [Fact]
+ public void TestNullDataContext()
+ {
+ var t = new Mock();
+ var sut = new XamlBinding(t.Object);
+ sut.BindToDataContext(null);
+ }
+ }
+}
diff --git a/tests/Perspex.Markup.Xaml.UnitTests/packages.config b/tests/Perspex.Markup.Xaml.UnitTests/packages.config
new file mode 100644
index 0000000000..c7f996e816
--- /dev/null
+++ b/tests/Perspex.Markup.Xaml.UnitTests/packages.config
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Perspex.RenderTests/Controls/BorderTests.cs b/tests/Perspex.RenderTests/Controls/BorderTests.cs
index 4e2606d8c1..0383bb01a6 100644
Binary files a/tests/Perspex.RenderTests/Controls/BorderTests.cs and b/tests/Perspex.RenderTests/Controls/BorderTests.cs differ
diff --git a/tests/Perspex.RenderTests/Controls/ImageTests.cs b/tests/Perspex.RenderTests/Controls/ImageTests.cs
index 90511ac125..2f43cbdae1 100644
Binary files a/tests/Perspex.RenderTests/Controls/ImageTests.cs and b/tests/Perspex.RenderTests/Controls/ImageTests.cs differ
diff --git a/tests/Perspex.RenderTests/GlobalSuppressions.cs b/tests/Perspex.RenderTests/GlobalSuppressions.cs
deleted file mode 100644
index 254dbfdb94..0000000000
--- a/tests/Perspex.RenderTests/GlobalSuppressions.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2015 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
- "StyleCop.CSharp.MaintainabilityRules",
- "SA1401:Fields must be private",
- Justification = "PerspexProperty fields should not be private.")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
- "StyleCop.CSharp.DocumentationRules",
- "SA1600:Elements must be documented",
- Justification = "Tests should be self-documenting")]
\ No newline at end of file
diff --git a/tests/Perspex.RenderTests/Media/ImageBrushTests.cs b/tests/Perspex.RenderTests/Media/ImageBrushTests.cs
new file mode 100644
index 0000000000..2c958977b7
--- /dev/null
+++ b/tests/Perspex.RenderTests/Media/ImageBrushTests.cs
@@ -0,0 +1,351 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Controls;
+using Perspex.Controls.Shapes;
+using Perspex.Layout;
+using Perspex.Media;
+using Perspex.Media.Imaging;
+using Xunit;
+
+#if PERSPEX_CAIRO
+namespace Perspex.Cairo.RenderTests.Media
+#else
+namespace Perspex.Direct2D1.RenderTests.Media
+#endif
+{
+ public class ImageBrushTests : TestBase
+ {
+ public ImageBrushTests()
+ : base(@"Media\ImageBrush")
+ {
+ }
+
+ private string BitmapPath
+ {
+ get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); }
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_Alignment_TopLeft()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Left,
+ AlignmentY = AlignmentY.Top,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_Alignment_Center()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Center,
+ AlignmentY = AlignmentY.Center,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_Alignment_BottomRight()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Right,
+ AlignmentY = AlignmentY.Bottom,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_Fill_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 920,
+ Height = 920,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.Fill,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_Uniform_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 300,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.Uniform,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_UniformToFill_NoTile()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 300,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.UniformToFill,
+ TileMode = TileMode.None,
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.Tile,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "TileMode.FlipX not yet supported on cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_FlipX_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipX,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+#if PERSPEX_CAIRO
+ [Fact(Skip = "TileMode.FlipY not yet supported on cairo")]
+#else
+ [Fact]
+#endif
+ public void ImageBrush_NoStretch_FlipY_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipY,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void ImageBrush_NoStretch_FlipXY_TopLeftDest()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Rectangle
+ {
+ Fill = new ImageBrush
+ {
+ Stretch = Stretch.None,
+ TileMode = TileMode.FlipXY,
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Source = new Bitmap(BitmapPath),
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+ }
+}
diff --git a/tests/Perspex.RenderTests/Media/LinearGradientBrushTests.cs b/tests/Perspex.RenderTests/Media/LinearGradientBrushTests.cs
index a2f00bfb07..8d5185096d 100644
--- a/tests/Perspex.RenderTests/Media/LinearGradientBrushTests.cs
+++ b/tests/Perspex.RenderTests/Media/LinearGradientBrushTests.cs
@@ -1,14 +1,21 @@
-namespace Perspex.Direct2D1.RenderTests.Media
-{
- using Perspex.Controls;
- using Perspex.Media;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Xunit;
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Controls;
+using Perspex.Media;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+#if PERSPEX_CAIRO
+namespace Perspex.Cairo.RenderTests.Media
+#else
+namespace Perspex.Direct2D1.RenderTests.Media
+#endif
+{
public class LinearGradientBrushTests : TestBase
{
public LinearGradientBrushTests() : base(@"Media\LinearGradientBrush")
@@ -16,7 +23,34 @@
}
[Fact]
- public void LinearGradientBrush_RedBlue_Fill()
+ public void LinearGradientBrush_RedBlue_Horizontal_Fill()
+ {
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Border
+ {
+ Background = new LinearGradientBrush
+ {
+ StartPoint = new RelativePoint(0, 0.5, RelativeUnit.Relative),
+ EndPoint = new RelativePoint(1, 0.5, RelativeUnit.Relative),
+ GradientStops =
+ {
+ new GradientStop { Color = Colors.Red, Offset = 0 },
+ new GradientStop { Color = Colors.Blue, Offset = 1 }
+ }
+ }
+ }
+ };
+
+ RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public void LinearGradientBrush_RedBlue_Vertical_Fill()
{
Decorator target = new Decorator
{
@@ -27,8 +61,8 @@
{
Background = new LinearGradientBrush
{
- StartPoint = new Point(0, 0.5),
- EndPoint = new Point(1, 0.5),
+ StartPoint = new RelativePoint(0.5, 0, RelativeUnit.Relative),
+ EndPoint = new RelativePoint(0.5, 1, RelativeUnit.Relative),
GradientStops =
{
new GradientStop { Color = Colors.Red, Offset = 0 },
@@ -38,8 +72,8 @@
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
}
}
diff --git a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
index 7b32a223ce..cae9d4fbf4 100644
--- a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
+++ b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs
@@ -1,17 +1,19 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Perspex.Controls;
+using Perspex.Controls.Shapes;
+using Perspex.Layout;
+using Perspex.Media;
+using Perspex.Media.Imaging;
+using Xunit;
+
+#if PERSPEX_CAIRO
+namespace Perspex.Cairo.RenderTests.Media
+#else
namespace Perspex.Direct2D1.RenderTests.Media
+#endif
{
- using Perspex.Controls;
- using Perspex.Controls.Shapes;
- using Perspex.Layout;
- using Perspex.Media;
- using Xunit;
-
public class VisualBrushTests : TestBase
{
public VisualBrushTests()
@@ -19,86 +21,45 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
}
- [Fact]
- public void VisualBrush_Align_TopLeft()
+ private string BitmapPath
{
- Decorator target = new Decorator
- {
- Padding = new Thickness(8),
- Width = 200,
- Height = 200,
- Child = new Rectangle
- {
- Fill = new VisualBrush
- {
- AlignmentX = AlignmentX.Left,
- AlignmentY = AlignmentY.Top,
- Stretch = Stretch.None,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
- }
- }
- };
-
- this.RenderToFile(target);
- this.CompareImages();
+ get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); }
}
- [Fact]
- public void VisualBrush_Align_Center()
+ private Control Visual
{
- Decorator target = new Decorator
+ get
{
- Padding = new Thickness(8),
- Width = 200,
- Height = 200,
- Child = new Rectangle
+ return new Panel
{
- Fill = new VisualBrush
+ Children = new Perspex.Controls.Controls
{
- AlignmentX = AlignmentX.Center,
- AlignmentY = AlignmentY.Center,
- Stretch = Stretch.None,
- Visual = new Border
+ new Image
+ {
+ Source = new Bitmap(BitmapPath),
+ },
+ new Border
{
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
+ BorderBrush = Brushes.Blue,
BorderThickness = 2,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
- Text = "Perspex",
- FontSize = 12,
+ FontSize = 24,
FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
+ Background = Brushes.Green,
+ Foreground = Brushes.Yellow,
+ Text = "VisualBrush",
}
}
}
- }
- };
-
- this.RenderToFile(target);
- this.CompareImages();
+ };
+ }
}
[Fact]
- public void VisualBrush_Align_BottomRight()
+ public void VisualBrush_NoStretch_NoTile_Alignment_TopLeft()
{
Decorator target = new Decorator
{
@@ -109,220 +70,156 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- AlignmentX = AlignmentX.Right,
- AlignmentY = AlignmentY.Bottom,
Stretch = Stretch.None,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Left,
+ AlignmentY = AlignmentY.Top,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_Stretch_Fill_Large()
+#endif
+ public void VisualBrush_NoStretch_NoTile_Alignment_Center()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 920,
- Height = 920,
+ Width = 200,
+ Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.Fill,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Center,
+ AlignmentY = AlignmentY.Center,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
[Fact]
- public void VisualBrush_Stretch_Uniform()
+ public void VisualBrush_NoStretch_NoTile_Alignment_BottomRight()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 920,
- Height = 820,
+ Width = 200,
+ Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.Uniform,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ AlignmentX = AlignmentX.Right,
+ AlignmentY = AlignmentY.Bottom,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_Stretch_UniformToFill()
+#endif
+ public void VisualBrush_Fill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 920,
- Height = 820,
+ Height = 920,
Child = new Rectangle
{
Fill = new VisualBrush
{
- Stretch = Stretch.UniformToFill,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ Stretch = Stretch.Fill,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_SourceRect_Absolute()
+#endif
+ public void VisualBrush_Uniform_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 200,
+ Width = 300,
Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(40, 40, 100, 100, OriginUnit.Pixels),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.Uniform,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_DestinationRect_Absolute()
+#endif
+ public void VisualBrush_UniformToFill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
- Width = 200,
+ Width = 300,
Height = 200,
Child = new Rectangle
{
Fill = new VisualBrush
{
- DestinationRect = new RelativeRect(92, 92, 92, 92, OriginUnit.Pixels),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.UniformToFill,
+ TileMode = TileMode.None,
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
[Fact]
- public void VisualBrush_SourceRect_DestinationRect_Absolute()
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource()
{
Decorator target = new Decorator
{
@@ -333,34 +230,24 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(40, 40, 100, 100, OriginUnit.Pixels),
- DestinationRect = new RelativeRect(92, 92, 92, 92, OriginUnit.Pixels),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_SourceRect_DestinationRect_Percent()
+#endif
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
@@ -371,34 +258,20 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Fill = new VisualBrush
{
- SourceRect = new RelativeRect(0.22, 0.22, 0.56, 0.56, OriginUnit.Percent),
- DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, OriginUnit.Percent),
- Visual = new Border
- {
- Width = 180,
- Height = 180,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new Ellipse
- {
- Width = 100,
- Height = 100,
- Fill = Brushes.Yellow,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center,
- }
- }
+ Stretch = Stretch.None,
+ TileMode = TileMode.None,
+ DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
[Fact]
- public void VisualBrush_Tile()
+ public void VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
@@ -410,34 +283,20 @@ namespace Perspex.Direct2D1.RenderTests.Media
Fill = new VisualBrush
{
Stretch = Stretch.None,
- TileMode = TileMode.Tile,
- DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, OriginUnit.Percent),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ TileMode = TileMode.None,
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
[Fact]
- public void VisualBrush_Tile_Alignment_BottomRight()
+ public void VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
{
Decorator target = new Decorator
{
@@ -450,34 +309,23 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Stretch = Stretch.None,
TileMode = TileMode.Tile,
- AlignmentX = AlignmentX.Right,
- AlignmentY = AlignmentY.Bottom,
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
+ DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "TileMode.FlipX not yet supported on cairo")]
+#else
[Fact]
- public void VisualBrush_FlipX()
+#endif
+ public void VisualBrush_NoStretch_FlipX_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -490,33 +338,22 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Stretch = Stretch.None,
TileMode = TileMode.FlipX,
- DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, OriginUnit.Percent),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "TileMode.FlipY not yet supported on cairo")]
+#else
[Fact]
- public void VisualBrush_FlipY()
+#endif
+ public void VisualBrush_NoStretch_FlipY_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -529,33 +366,22 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Stretch = Stretch.None,
TileMode = TileMode.FlipY,
- DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, OriginUnit.Percent),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
+#if PERSPEX_CAIRO
+ [Fact(Skip = "Font scaling currently broken on cairo")]
+#else
[Fact]
- public void VisualBrush_FlipXY()
+#endif
+ public void VisualBrush_NoStretch_FlipXY_TopLeftDest()
{
Decorator target = new Decorator
{
@@ -568,29 +394,14 @@ namespace Perspex.Direct2D1.RenderTests.Media
{
Stretch = Stretch.None,
TileMode = TileMode.FlipXY,
- DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, OriginUnit.Percent),
- Visual = new Border
- {
- Width = 92,
- Height = 92,
- Background = Brushes.Red,
- BorderBrush = Brushes.Black,
- BorderThickness = 2,
- Child = new TextBlock
- {
- Text = "Perspex",
- FontSize = 12,
- FontFamily = "Arial",
- HorizontalAlignment = HorizontalAlignment.Center,
- VerticalAlignment = VerticalAlignment.Center,
- }
- }
+ DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
+ Visual = Visual,
}
}
};
- this.RenderToFile(target);
- this.CompareImages();
+ RenderToFile(target);
+ CompareImages();
}
}
}
diff --git a/tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj b/tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj
index ffeb20949a..ac99be3bdf 100644
--- a/tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj
+++ b/tests/Perspex.RenderTests/Perspex.Cairo.RenderTests.csproj
@@ -1,5 +1,6 @@
+
@@ -8,8 +9,8 @@
{E106CF37-4066-4615-B684-172A6D30B058}
Library
Properties
- Perspex.Direct2D1.RenderTests
- Perspex.Direct2D1.RenderTests
+ Perspex.Cairo.RenderTests
+ Perspex.Cairo.RenderTests
v4.5
512
10.0
@@ -17,7 +18,8 @@
$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
False
UnitTest
- 93023d49
+
+
true
@@ -32,38 +34,31 @@
pdbonly
true
bin\Release\
- TRACE
+ TRACE;PERSPEX_CAIRO
prompt
4
-
- ..\..\packages\Magick.NET-Q8-x86.7.0.0.0014\lib\net40-client\Magick.NET-x86.dll
- True
-
-
- ..\..\packages\Magick.NET-Q8-x86.7.0.0.0014\lib\net40-client\Magick.NET.Core.dll
- True
-
-
- ..\..\packages\Magick.NET-Q8-x86.7.0.0.0014\lib\net40-client\Magick.NET.Wrapper-x86.dll
- True
-
-
- ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
- True
-
-
- ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
-
..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll
..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll
+
+ ..\..\packages\Magick.NET-Q16-AnyCPU.7.0.0.0018\lib\net40-client\Magick.NET-AnyCPU.dll
+
+
+ ..\..\packages\Magick.NET-Q16-AnyCPU.7.0.0.0018\lib\net40-client\Magick.NET.Core.dll
+
+
+ ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll
+
+
+ ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
+
@@ -76,6 +71,9 @@
+
+
+
@@ -83,40 +81,40 @@
-
- {fb05ac90-89ba-4f2f-a924-f37875fb547c}
+
+ {FB05AC90-89BA-4F2F-A924-F37875FB547C}
Perspex.Cairo
-
- {d211e587-d8bc-45b9-95a4-f297c8fa5200}
+
+ {D211E587-D8BC-45B9-95A4-F297C8FA5200}
Perspex.Animation
-
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
+
+ {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
Perspex.Base
-
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
+
+ {D2221C82-4A25-4583-9B43-D791E3F6820C}
Perspex.Controls
-
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
+
+ {62024B2D-53EB-4638-B26B-85EEAA54866E}
Perspex.Input
-
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
+
+ {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
Perspex.Interactivity
-
- {42472427-4774-4c81-8aff-9f27b8e31721}
+
+ {42472427-4774-4C81-8AFF-9F27B8E31721}
Perspex.Layout
-
- {eb582467-6abb-43a1-b052-e981ba910e3a}
+
+ {EB582467-6ABB-43A1-B052-E981BA910E3A}
Perspex.SceneGraph
-
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
+
+ {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
Perspex.Styling
@@ -152,7 +150,7 @@
This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+