Browse Source

Add Button over/pressed and pressed states

pull/4/head
Steven Kirk 13 years ago
parent
commit
5c1c26be93
  1. 1
      Perspex.UnitTests/Perspex.UnitTests.csproj
  2. 16
      Perspex.UnitTests/Styling/SelectorTests_Class.cs
  3. 55
      Perspex.UnitTests/Styling/SelectorTests_Multiple.cs
  4. 19
      Perspex.Windows/Input/MouseDevice.cs
  5. 9
      Perspex/Controls/Border.cs
  6. 3
      Perspex/Controls/Control.cs
  7. 66
      Perspex/Input/InputManager.cs
  8. 5
      Perspex/Point.cs
  9. 10
      Perspex/Themes/Default/ButtonStyle.cs
  10. 11
      Perspex/VisualExtensions.cs

1
Perspex.UnitTests/Perspex.UnitTests.csproj

@ -77,6 +77,7 @@
<Compile Include="PerspexObjectTests.cs" />
<Compile Include="StyleTests.cs" />
<Compile Include="Styling\ActivatorTests.cs" />
<Compile Include="Styling\SelectorTests_Multiple.cs" />
<Compile Include="Styling\SelectorTests_Class.cs" />
<Compile Include="Styling\SelectorTests_Id.cs" />
<Compile Include="Styling\SelectorTests_OfType.cs" />

16
Perspex.UnitTests/Styling/SelectorTests_Class.cs

@ -94,6 +94,22 @@ namespace Perspex.UnitTests.Styling
Assert.IsFalse(ActivatorValue(target, control));
}
[TestMethod]
public void Multiple_Classes()
{
var control = new Control1();
var target = new Selector().Class("foo").Class("bar");
var activator = target.GetActivator(control);
Assert.IsFalse(ActivatorValue(target, control));
control.Classes.Add("foo");
Assert.IsFalse(ActivatorValue(target, control));
control.Classes.Add("bar");
Assert.IsTrue(ActivatorValue(target, control));
control.Classes.Remove("bar");
Assert.IsFalse(ActivatorValue(target, control));
}
private static bool ActivatorValue(Selector selector, IStyleable control)
{
return selector.GetActivator(control).Take(1).ToEnumerable().Single();

55
Perspex.UnitTests/Styling/SelectorTests_Multiple.cs

@ -0,0 +1,55 @@
// -----------------------------------------------------------------------
// <copyright file="SelectorTests.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.UnitTests.Styling
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Perspex.Controls;
using Perspex.Styling;
[TestClass]
public class SelectorTests_Multiple
{
[TestMethod]
public void Template_Child_Of_Control_With_Two_Classes()
{
var template = new ControlTemplate(parent =>
{
return new Border
{
Id = "border",
};
});
var control = new Button
{
Template = template,
};
var selector = new Selector()
.OfType<Button>()
.Class("foo")
.Class("bar")
.Template()
.Id("border");
var border = (Border)((IVisual)control).VisualChildren.Single();
var values = new List<bool>();
var activator = selector.GetActivator(border);
activator.Subscribe(x => values.Add(x));
CollectionAssert.AreEqual(new[] { false }, values);
control.Classes.Add("foo", "bar");
CollectionAssert.AreEqual(new[] { false, true }, values);
control.Classes.Remove("foo");
CollectionAssert.AreEqual(new[] { false, true, false }, values);
}
}
}

19
Perspex.Windows/Input/MouseDevice.cs

@ -43,14 +43,17 @@ namespace Perspex.Windows.Input
{
this.Captured = visual;
RawMouseEventArgs e = new RawMouseEventArgs(
this,
this.CurrentWindow,
RawMouseEventType.Move,
this.Position);
IInputManager inputManager = Locator.Current.GetService<IInputManager>();
inputManager.Process(e);
if (visual == null)
{
RawMouseEventArgs e = new RawMouseEventArgs(
this,
this.CurrentWindow,
RawMouseEventType.Move,
this.Position);
IInputManager inputManager = Locator.Current.GetService<IInputManager>();
inputManager.Process(e);
}
}
}
}

9
Perspex/Controls/Border.cs

@ -12,6 +12,15 @@ namespace Perspex.Controls
public class Border : Decorator
{
public Border()
{
// Hacky hack hack!
Observable.Merge(
this.GetObservable(BackgroundProperty),
this.GetObservable(BorderBrushProperty))
.Subscribe(_ => this.InvalidateArrange());
}
public override void Render(IDrawingContext context)
{
Brush background = this.Background;

3
Perspex/Controls/Control.cs

@ -123,9 +123,6 @@ namespace Perspex.Controls
this.Classes.Remove(":pointerover");
}
});
// Hacky hack hack!
this.GetObservable(BackgroundProperty).Skip(1).Subscribe(_ => this.InvalidateMeasure());
}
public event EventHandler<PointerEventArgs> PointerEnter

66
Perspex/Input/InputManager.cs

@ -45,35 +45,18 @@ namespace Perspex.Input
{
if (device.Captured == null)
{
IEnumerable<IVisual> hits = visual.GetVisualsAt(p);
this.UpdatePointerOver(device, visual, p);
}
else
{
Point offset = new Point();
foreach (var control in this.pointerOvers.ToList().Except(hits).Cast<Control>())
foreach (IVisual ancestor in device.Captured.GetVisualAncestors())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = Control.PointerLeaveEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Remove(control);
control.RaiseEvent(e);
offset += ancestor.Bounds.Position;
}
foreach (var control in hits.Except(this.pointerOvers).Cast<Control>())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = Control.PointerEnterEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Add(control);
control.RaiseEvent(e);
}
this.UpdatePointerOver(device, device.Captured, p - offset);
}
}
@ -118,5 +101,38 @@ namespace Perspex.Input
}
}
}
private void UpdatePointerOver(IPointerDevice device, IVisual visual, Point p)
{
IEnumerable<IVisual> hits = visual.GetVisualsAt(p);
foreach (var control in this.pointerOvers.ToList().Except(hits).Cast<Control>())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = Control.PointerLeaveEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Remove(control);
control.RaiseEvent(e);
}
foreach (var control in hits.Except(this.pointerOvers).Cast<Control>())
{
PointerEventArgs e = new PointerEventArgs
{
RoutedEvent = Control.PointerEnterEvent,
Device = device,
OriginalSource = control,
Source = control,
};
this.pointerOvers.Add(control);
control.RaiseEvent(e);
}
}
}
}

5
Perspex/Point.cs

@ -50,6 +50,11 @@ namespace Perspex
get { return this.y; }
}
public static Point operator +(Point a, Point b)
{
return new Point(a.x + b.x, a.y + b.y);
}
public static Point operator -(Point a, Point b)
{
return new Point(a.x - b.x, a.y - b.y);

10
Perspex/Themes/Default/ButtonStyle.cs

@ -40,12 +40,18 @@ namespace Perspex.Themes.Default
new Setter (Button.BorderBrushProperty, new SolidColorBrush(0xff3c7fb1)),
},
},
new Style(x => x.OfType<Button>().Class(":pressed").Template().Id("border"))
new Style(x => x.OfType<Button>().Class(":pointerover").Class(":pressed").Template().Id("border"))
{
Setters = new[]
{
new Setter (Button.BackgroundProperty, new SolidColorBrush(0xffc4e5f6)),
new Setter (Button.BorderBrushProperty, new SolidColorBrush(0xff2c628b)),
},
},
new Style(x => x.OfType<Button>().Class(":pressed").Template().Id("border"))
{
Setters = new[]
{
new Setter (Button.BorderBrushProperty, new SolidColorBrush(0xffff628b)),
},
},
});

11
Perspex/VisualExtensions.cs

@ -58,6 +58,17 @@ namespace Perspex
return (visual as T) ?? visual.GetVisualAncestor<T>();
}
public static IEnumerable<IVisual> GetVisualAncestors(this IVisual visual)
{
visual = visual.VisualParent;
while (visual != null)
{
yield return visual;
visual = visual.VisualParent;
}
}
public static IVisual GetVisualAt(this IVisual visual, Point p)
{
Contract.Requires<NullReferenceException>(visual != null);

Loading…
Cancel
Save