From 7aec2d141cabecd5f590aee3660be324312de0f1 Mon Sep 17 00:00:00 2001 From: Kai Eichinger Date: Thu, 11 Dec 2014 15:48:45 +0100 Subject: [PATCH 1/3] Added syntax highlighting to intro.md --- Docs/intro.md | 146 ++++++++++++++++++++++++++++---------------------- 1 file changed, 83 insertions(+), 63 deletions(-) diff --git a/Docs/intro.md b/Docs/intro.md index aba5ea14897..08d8da812a3 100644 --- a/Docs/intro.md +++ b/Docs/intro.md @@ -36,32 +36,36 @@ Attached Properties. So the challenge became to improve it. Delaring a DP in WPF looks something like this: - public static readonly DependencyProperty PropertyDeclaration = - DependencyProperty.Register( - "PropertyName", - typeof(PropertyType), - typeof(OwnerClass), - new FrameworkPropertyMetadata( - default(PropertyType), - FrameworkPropertyMetadataOptions.Inherits)); - - public PropertyType PropertyName - { - get { return (PropertyType)this.GetValue(PropertyDeclaration); } - set { this.SetValue(PropertyDeclaration, value); } - } +```csharp +public static readonly DependencyProperty PropertyDeclaration = +DependencyProperty.Register( + "PropertyName", + typeof(PropertyType), + typeof(OwnerClass), + new FrameworkPropertyMetadata( + default(PropertyType), + FrameworkPropertyMetadataOptions.Inherits)); + +public PropertyType PropertyName +{ + get { return (PropertyType)this.GetValue(PropertyDeclaration); } + set { this.SetValue(PropertyDeclaration, value); } +} +``` Eww! All that just to declare a single property. There's **A LOT** of boilerplate there. With generics and default parameters we can at least make it look a bit nicer: - public static readonly PerspexProperty PropertyDeclaration = - PerspexProperty.Register("PropertyName", inherits: true); +```csharp +public static readonly PerspexProperty PropertyDeclaration = +PerspexProperty.Register("PropertyName", inherits: true); - public PropertyType PropertyName - { - get { return this.GetValue(PropertyDeclaration); } - set { this.SetValue(PropertyDeclaration, value); } - } +public PropertyType PropertyName +{ + get { return this.GetValue(PropertyDeclaration); } + set { this.SetValue(PropertyDeclaration, value); } +} +``` What can we see here? @@ -77,34 +81,42 @@ write typeof() twice. Binding in Perspex uses Reactive Extensions' IObservable. To bind an IObservable to a property, use the Bind method: - control.Bind(BorderProperty, someObject.SomeObservable()); +```csharp +control.Bind(BorderProperty, someObject.SomeObservable()); +``` Note that because PerspexProperty is typed, we can check that the observable is of the correct type. To get the value of a property as an observable, call GetObservable(): - var observable = control.GetObservable(Control.FooProperty); +```csharp +var observable = control.GetObservable(Control.FooProperty); +``` ## Attached Properties and Binding Pt 2 Attached properties are set just like in WPF, using SetValue. But what about the [] operator? C# 6 will allow us to use [] array subscripts in object initializers. So how does this look? - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", +} +``` Nice... Lets take this further: - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - [!Property2] = something.SomeObservable, - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", + [!Property2] = something.SomeObservable, +} +``` Yep, by putting a bang in front of the property name you can **bind** to a property (attached or otherwise) from the object initializer. @@ -120,12 +132,14 @@ Binding to a property on another control? Easy: Two way binding? Just add two bangs: - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - [!!Property2] = anotherControl[!!Property1], - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", + [!!Property2] = anotherControl[!!Property1], +} +``` ## Visual and Logical trees @@ -144,36 +158,42 @@ property, which is determined by... Styles in Perspex diverge from styles in WPF quite a lot, and move towards a more CSS-like system. It's probably easiest to show in an example. Here is the default style for the CheckBox control: - new Style(x => x.OfType()) - { - Setters = new[] - { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), - }, - }, - new Style(x => x.OfType().Template().Id("checkMark")) - { - Setters = new[] - { - new Setter(Shape.IsVisibleProperty, false), - }, - }, - new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) - { - Setters = new[] - { - new Setter(Shape.IsVisibleProperty, true), - }, - }, +```csharp +new Style(x => x.OfType()) +{ +Setters = new[] +{ + new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), +}, +}, +new Style(x => x.OfType().Template().Id("checkMark")) +{ +Setters = new[] +{ + new Setter(Shape.IsVisibleProperty, false), +}, +}, +new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +{ +Setters = new[] +{ + new Setter(Shape.IsVisibleProperty, true), +}, +}, +``` Let's see what's happening here: - new Style(x => x.OfType()) +```csharp +new Style(x => x.OfType()) +``` The constructor for the Style class defines the selector. Here we're saying "*this style applies to all controls in the the visual tree of type CheckBox*". A more complex selector: - new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +```csharp +new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) +``` This selector matches "*all controls with Id == "checkMark" in the template of a CheckBox with the class ':checked'"*. Each control has an Id property, and Ids in templates are considered to be in a From e5099390c1ede6338f514d00c3d4c4d0007a1b99 Mon Sep 17 00:00:00 2001 From: Kai Eichinger Date: Fri, 12 Dec 2014 21:36:26 +0100 Subject: [PATCH 2/3] Updated intro.md - Rewrote a few sections - Fixed code formatting - Added external references - Added better highlighting of important classes and keywords in various sections --- Docs/intro.md | 75 ++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/Docs/intro.md b/Docs/intro.md index 08d8da812a3..4b0fae65a1b 100644 --- a/Docs/intro.md +++ b/Docs/intro.md @@ -17,7 +17,8 @@ So I began to think: what if we were to start anew with modern C# features such Generics, Observables, async, etc etc. The result of that thought is Perspex (https://github.com/grokys/Perspex). -**DISCLAIMER**: This is really early development pre-alpha-alpha stuff. Everything is subject to +##### DISCLAIMER +This is really **early development pre-alpha-alpha** stuff. Everything is subject to change, I'm not even sure if the performance characteristics of Rx make Observables suitable for binding throughout a framework. *I'm writing this only to see if the idea of exploring these ideas appeals to anyone else.* @@ -70,16 +71,15 @@ public PropertyType PropertyName What can we see here? - PerpexProperties are typed, so no more having to cast in the getter. -- We pass the property type and owner class as a generic type to Register() so we don't have to -write typeof() twice. -- We used default parameter values in Rigister() so that defaults don't have to be restated. +- We pass the property type and owner class as a generic type to `Register()` so we don't have to +write `typeof()` twice. +- We used default parameter values in `Register()` so that defaults don't have to be restated. *(ASIDE: maybe Roslyn will give us [var for fields](http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx)...)? Lets hope...* ## Binding -Binding in Perspex uses Reactive Extensions' IObservable. To bind an IObservable to a property, -use the Bind method: +Binding in Perspex uses Reactive Extensions' [IObservable](http://msdn.microsoft.com/library/dd990377.aspx). To bind an IObservable to a property, use the `Bind()` method: ```csharp control.Bind(BorderProperty, someObject.SomeObservable()); @@ -87,7 +87,7 @@ control.Bind(BorderProperty, someObject.SomeObservable()); Note that because PerspexProperty is typed, we can check that the observable is of the correct type. -To get the value of a property as an observable, call GetObservable(): +To get the value of a property as an observable, call `GetObservable()`: ```csharp var observable = control.GetObservable(Control.FooProperty); @@ -95,8 +95,7 @@ var observable = control.GetObservable(Control.FooProperty); ## Attached Properties and Binding Pt 2 -Attached properties are set just like in WPF, using SetValue. But what about the [] operator? C# 6 -will allow us to use [] array subscripts in object initializers. So how does this look? +Attached properties are set just like in WPF, using `SetValue()`. But what about the `[]` operator, also called [index initializer](https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status&referringTitle=Home) (see *C# feature descriptions*)? The upcoming version of C# will provide a new feature that allows us to use `[]` array subscripts in object initializers. An example on how to make use of it will look like this: ```csharp var control = new Control @@ -123,12 +122,14 @@ otherwise) from the object initializer. Binding to a property on another control? Easy: - var control = new Control - { - Property1 = "Foo", - [Attached.Property] = "Bar", - [!Property2] = anotherControl[!Property1], - } +```csharp +var control = new Control +{ + Property1 = "Foo", +[Attached.Property] = "Bar", + [!Property2] = anotherControl[!Property1], +} +``` Two way binding? Just add two bangs: @@ -146,7 +147,7 @@ var control = new Control Perspex uses the same visual/logical tree separation that is used by WPF (and to some extent HTML is moving in this direction with the Shadow DOM). The manner of accessing the two trees is slightly different however. Rather than using Visual/LogicalTreeHelper you can cast any control to an -IVisual or ILogical to reveal the tree operations. There's also the VisualExtensions class which +`IVisual` or `ILogical` to reveal the tree operations. There's also the VisualExtensions class which provides some useful extension methods such as `GetVisualAncestor(this IVisual visual)` or `GetVisualAt(this IVisual visual, Point p)`. @@ -161,25 +162,27 @@ It's probably easiest to show in an example. Here is the default style for the C ```csharp new Style(x => x.OfType()) { -Setters = new[] -{ - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), -}, -}, + Setters = new[] + { + new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)) + } +}; + new Style(x => x.OfType().Template().Id("checkMark")) { -Setters = new[] -{ - new Setter(Shape.IsVisibleProperty, false), -}, -}, + Setters = new[] + { + new Setter(Shape.IsVisibleProperty, false) + } +}; + new Style(x => x.OfType().Class(":checked").Template().Id("checkMark")) { -Setters = new[] -{ - new Setter(Shape.IsVisibleProperty, true), -}, -}, + Setters = new[] + { + new Setter(Shape.IsVisibleProperty, true) + } +}; ``` Let's see what's happening here: @@ -196,14 +199,14 @@ new Style(x => x.OfType().Class(":checked").Template().Id("checkMark") ``` This selector matches "*all controls with Id == "checkMark" in the template of a CheckBox with the -class ':checked'"*. Each control has an Id property, and Ids in templates are considered to be in a +class `:checked`"*. Each control has an Id property, and Ids in templates are considered to be in a separate namespace. Inside the Style class we then have a collection of setters similar to WPF. This system means that there's no more need for WPF's Triggers - the styling works with classes -(which are arbitrary strings) similar to CSS. Similar to CSS, classes with a leading ":" are set -by the control itself in response to events like mouseover and click. +(which are arbitrary strings) similar to CSS. Similar to CSS, classes with a leading `:` are set +by the control itself in response to events like `mouseover` and `click`. Similar to WPF, styles can be defined on each control, with a global application style collection at the root. This means that different subsections of the visual tree can have a completely @@ -212,11 +215,11 @@ different look-and-feel. ## XAML As you can see, all of the examples here are defined in code - but a XAML implementation is being -worked on (https://github.com/SuperJMN/Perspex/tree/xamlreader) +worked on. The current progress can be reviewed at https://github.com/SuperJMN/Perspex/tree/fuent-api. ## That's all for now There's a lot more to see, and even more to do, so if you want to have a play you can get the code here: [https://github.com/grokys/Perspex](https://github.com/grokys/Perspex) -Feedback welcome! +Feedback is always welcome! From a5d56fd5e8b21f8f775febc8167b22d2018edaba Mon Sep 17 00:00:00 2001 From: Kai Eichinger Date: Fri, 12 Dec 2014 21:57:49 +0100 Subject: [PATCH 3/3] Splitted first block into a new "documentary" section. Added "building and using" section --- readme.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 592f05734f9..5d0abfe4468 100644 --- a/readme.md +++ b/readme.md @@ -19,11 +19,19 @@ generics. So I began to think: what if we were to start anew with modern C# features such as *(gasp)* Generics, Observables, async, etc etc. The result of that thought is Perspex. -**DISCLAIMER**: This is really early development pre-alpha-alpha stuff. Everything is subject to +##### DISCLAIMER +This is really early development pre-alpha-alpha stuff. Everything is subject to change, I'm not even sure if the performance characteristics of Rx make Observables suitable for binding throughout a framework. *I'm writing this only to see if the idea of exploring these ideas appeals to anyone else.* -[Take a look at the introduction document here.](Docs/intro.md) +## Documentary +Like mentioned above this is really an early version of Perplex and we're working hard on improving the code base and the documentary at the same time. Please feel free to have a look at our [introduction document](Docs/intro.md) to get things started real quick. Contributions are always welcome! -**NOTE**: This uses proposed C#6 features so you'll have to install a Roslyn preview. [If you're using VS2013, try here.]( https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=52793) +## Building and Using +In order to build and use Perpex you need a compiler that supports the upcoming C# 6 features. + +- **Visual Studio 2015 Preview**: The recommended way to compile C# 6 code is to use the new Visual Studio 2015 Preview version, which Microsoft has released later this year. It comes with the new Roslyn compiler and features like the new upcoming JIT (RyuJIT) and other improvements like extensible code analysis right out of the box. It can be downloaded [here](http://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs) + +- **Visual Studio 2013**: With the introductory of the new Roslyn compiler platform earlier this year Microsoft has released an *April End User Preview* which is a small extension that brings supports to Visual Studio 2013.
+ **NOTE**: This extension is **out of date** and will **no longer be updated**, according to the [Roslyn CodePlex](https://roslyn.codeplex.com/) main page. However, if you don't want to use a Preview IDE feel free to download the extension [over here](https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=52793). It must be noted that it is not guaranteed that future versions of Perplex will compile and run when using this extension.